Scrapy框架(三)
CrawlSpider
創(chuàng)建CrawlSpider
命令:
scrapy genspider -t crawl hr.tencent hr.tencent.com
url 就是你想要爬取的網(wǎng)址
注意:分析本地文件是一定要帶上路徑,scrapy shell默認(rèn)當(dāng)作url
Rule
Rule用來(lái)定義CrawlSpider的爬取規(guī)則
參數(shù):
link_extractor Link Extractor對(duì)象论皆,它定義如何從每個(gè)已爬網(wǎng)頁(yè)面中提取鏈接。
callback 回調(diào)函數(shù)
cb_kwargs 是一個(gè)包含要傳遞給回調(diào)函數(shù)的關(guān)鍵字參數(shù)的dict
follow 它指定是否應(yīng)該從使用此規(guī)則提取的每個(gè)響應(yīng)中跟蹤鏈接猾漫。
process_links 用于過(guò)濾連接的回調(diào)函數(shù)
process_request 用于過(guò)濾請(qǐng)求的額回調(diào)函數(shù)
LinkExtractor
LinkExractor也是scrapy框架定義的一個(gè)類(lèi)它唯一的目的是從web頁(yè)面中提取最終將被跟蹤的額連接点晴。
我們也可定義我們自己的鏈接提取器,只需要提供一個(gè)名為extract_links的方法悯周,它接收Response對(duì)象并返回scrapy.link.Link對(duì)象列表粒督。
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class MeishiSpider(CrawlSpider):
"""
scrapy 爬靜態(tài)的
CrawlSpider 在多頁(yè)情況下, 已經(jīng)數(shù)據(jù)為純靜態(tài)的情況 用來(lái)爬取全站數(shù)據(jù).
Spider
"""
name = 'meishi'
allowed_domains = ['www.meishij.net']
start_urls = ['https://www.meishij.net/chufang/diy/?&page=1']
rules = (
# allow: 指定正則匹配的唯一標(biāo)準(zhǔn), 不用把正則表達(dá)式寫(xiě)完整, 只要能體現(xiàn)唯一性且在網(wǎng)頁(yè)源代碼中匹配到的數(shù)據(jù)就是目標(biāo)數(shù)據(jù)
# 這里的page=\d+ 雖然表示不能代表整個(gè)翻頁(yè)的URL, 但是沒(méi)關(guān)系, LinkExtractor會(huì)幫我們找到匹配項(xiàng)并直接獲取其完整URL
# callback: Rule規(guī)則發(fā)送的后續(xù)請(qǐng)求, 所返回的響應(yīng)應(yīng)該交給誰(shuí)(方法名)來(lái)進(jìn)行處理
# callback不能寫(xiě)parse, parse會(huì)在CrawlSpider自己調(diào)用.
# follow: 首先項(xiàng)目開(kāi)始運(yùn)行后, 發(fā)送的第一批請(qǐng)求會(huì)被Rule進(jìn)行規(guī)則檢查, 若在響應(yīng)的數(shù)據(jù)中匹配到相關(guān)URL, 那么就會(huì)跟進(jìn)(發(fā)送)該URL
# 但是跟進(jìn)的請(qǐng)求也會(huì)有響應(yīng), 響應(yīng)中也可能會(huì)包含符合allow表達(dá)式匹配的URL. 如果想要進(jìn)一步匹配這些URL并跟進(jìn), 就設(shè)置follow=True,
# 如果不想跟進(jìn)就設(shè)置為False
# 前面Rule發(fā)送的請(qǐng)求返回的響應(yīng), 會(huì)被下面的Rule也就進(jìn)行匹配, 所以若你Rule設(shè)置太多. 邏輯復(fù)雜容易出問(wèn)題
# 1. 該Rule是匹配響應(yīng)中的頁(yè)碼URL, 匹配到了就跟進(jìn)請(qǐng)求, 若跟進(jìn)的響應(yīng)中也包含了頁(yè)碼URL, 那么就再跟進(jìn)(重復(fù)的URL會(huì)自動(dòng)去重)
# 直到?jīng)]有匹配新的URL為止
Rule(LinkExtractor(allow=r'page=\d+'), callback='parse_item', follow=True),
# 2. 該Rule是匹配每一頁(yè)菜品的詳情URL, 匹配到就跟進(jìn), 跟進(jìn)返回的響應(yīng)交給parse_detail
Rule(LinkExtractor(allow=r'zuofa/'), callback='parse_detail', follow=False),
)
def parse_item(self, response):
"""
獲取每頁(yè)的菜品基本信息
:param response:
:return:
"""
# PameishiItem 該類(lèi)描述的目標(biāo)字段是菜品基本信息
item = PameishiItem()
node_list = response.xpath("http://div[@class='listtyle1']")
for node in node_list:
item["title"] = node.xpath("./a/@title").extract_first()
item["title_url"] = node.xpath("./a/@href").extract_first()
item["title_img_url"] = node.xpath("./a/img/@src").extract_first()
item["use_time"] = node.xpath(".//ul/li[1]/text()").extract_first()
item["pattern_flavor"] = node.xpath(".//ul/li[2]/text()").extract_first()
yield item
案例實(shí)踐
piplines文件
1560431483911.png
1560431511676.png
CrawlSpider頁(yè)面去重
1560431542255.png
scrapy去重機(jī)制
1560431570470.png
總結(jié):
scrapy只會(huì)將請(qǐng)求報(bào)文完全相同的對(duì)象視為相同請(qǐng)求.
對(duì)這樣的相同請(qǐng)求對(duì)象進(jìn)行過(guò)濾, 過(guò)濾原理大致為: 將請(qǐng)求的對(duì)象的相關(guān)信息, 如url, headers, 參數(shù)數(shù)據(jù)等.
通過(guò)單向加密加密成等長(zhǎng)數(shù)據(jù), 然后對(duì)加密后的數(shù)據(jù)進(jìn)行對(duì)比, 來(lái)實(shí)現(xiàn)去重.
1560431603728.png
作業(yè)
1.使用CrawlSpider實(shí)現(xiàn)爬取美食網(wǎng)站上的相關(guān)信息,并導(dǎo)出為兩個(gè)json數(shù)據(jù)文件, 分為基本信息json, 詳情信息json.
要求:運(yùn)行成功為前提禽翼,只要spider代碼的截圖和兩個(gè)文件部分信息截圖