1. 程式人生 > >利用scrapy框架遞迴爬取菜譜網站

利用scrapy框架遞迴爬取菜譜網站

介紹:

最近學習完scrapy框架後,對整個執行過程有了進一步的瞭解熟悉。於是想著利用該框架對食譜網站上的美食圖片進行抓取,並且分別按照各自的命名進行儲存。

1、網頁分析

爬取的網站是www.xinshipu.com,在爬取的過程中我發現使用xpath對網頁進行解析時總是找不到對應的標籤,但是xpath路徑又沒有錯誤。這點一直讓我很費解,直到我手動將request獲取到的響應原始碼儲存到本地進行檢視時才發現,請求到的網頁跟瀏覽器端開啟的網頁結構完全不一樣。後來通過檢視圖片的儲存路徑我發現網站上的圖片都是儲存在阿里的伺服器上,因此猜想應該是阿里做的反爬蟲的處理導致直接分析網頁原始碼會失效吧,這點到底怎麼實現的,因為現在還是小白,所以暫時還不清楚,留待以後解決吧。

如上圖所示,為每道菜的網頁原始碼,初步設想可以爬取a標籤並用rel屬性用作識別條件,然後將底下的img標籤的src屬性拿到。該屬性是每道菜圖片的儲存地址。然後獲得p標籤中的文字內容。

對於每頁的連結地址,網頁原始碼如下:

 

這裡可以獲取a標籤並且以rel屬性用作識別條件,然後將識別出的a標籤的href屬性提取出來,然後將它和網站的域名結合起來,傳遞給排程器進行處理。

2、實現 

(1)實現資料的提取

首先定義資料物件結構,

import scrapy


class XinshipuItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()
    img=scrapy.Field()
    pass

 如圖所示,定義了圖片的名字,以及圖片的儲存地址兩個屬性。

然後解析網頁標籤,如圖所示,將每一個獲得資訊yield返回給pipline進行處理。

import scrapy
import requests
from xinshipu.items import XinshipuItem

class JiachangcaiSpider(scrapy.Spider):
    name = 'jiachangcai'
    allowed_domains = ['www.xinshipu.com']
    start_urls = ['https://www.xinshipu.com/jiachangzuofa/17844/']

    def parse(self, response):
        for each in response.xpath("//a[@rel='ImgClk']"):
            item= XinshipuItem()
            img=each.xpath("div/img/@src").extract()
            name=each.xpath("div/div/p/text()").extract()
            item['name']=name[0]
            item['img'] = img[0]
            yield item

接著對下一頁的url進行提取,將提取的url組合後提交給排程器,通過回撥函式呼叫parse進行解析。

suburl=response.xpath('//a[@rel="next"]/@href').extract()
        url_next="https://www.xinshipu.com%s"%suburl[0]
        print(url_next)
        yield scrapy.http.Request(url_next, callback=self.parse)

最後在pipline中對每一個item進行資料持久化操作,儲存到本地並以對應的名字命名。

import requests
from requests import Session
class XinshipuPipeline(object):
    def process_item(self, item, spider):
        #print(item['img'])
        img=requests.get(url="https:%s"%item['img'])


        name=item['name']
        print(name)
        with open("%s.jpg"%name,"wb") as f:
            f.write(img.content)
            f.close()

        return item

3、結果

執行scrapy crawl jiachangcai 命令,得到爬取的結果:

總結補充

爬取過程中可以通過在setting中設定DEPTH_LIMT屬性控制迭代網頁的深度,但是我在設定後並沒有起相關的作用,這裡咱們不太清楚什麼原因,留待以後解決吧!