scrapy通用爬蟲

  • CrawlSpider它是Spider的派生類,Spider類的設計原則是只爬取start_url列表中的網頁,而CrawlSpider類定義了一些規則Rule來提供跟進鏈接的方便的機制,從爬取的網頁結果中獲取鏈接并繼續爬取的工作。

源碼參考

class CrawlSpider(Spider):
    rules = ()
    def __init__(self, *a, **kw):
    super(CrawlSpider, self).__init__(*a, **kw)
    self._compile_rules()

#首先調用parse()來處理start_urls中返回的response對象
#parse()則將這些response對象傳遞給了_parse_response()函數處理,并設置回調函數為parse_start_url()
#設置了跟進標志位True
#parse將返回item和跟進了的Request對象
def parse(self, response):
return self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True)

#處理start_url中返回的response,需要重寫
def parse_start_url(self, response):
return []

def process_results(self, response, results):
return results

#從response中抽取符合任一用戶定義'規則'的鏈接,并構造成Resquest對象返回
def _requests_to_follow(self, response):
if not isinstance(response, HtmlResponse):
return
seen = set()
#抽取之內的所有鏈接,只要通過任意一個'規則',即表示合法
for n, rule in enumerate(self._rules):
links = [l for l in rule.link_extractor.extract_links(response) if l not in seen]
#使用用戶指定的process_links處理每個連接
if links and rule.process_links:
links = rule.process_links(links)
#將鏈接加入seen集合,為每個鏈接生成Request對象,并設置回調函數為_repsonse_downloaded()
for link in links:
seen.add(link)
#構造Request對象,并將Rule規則中定義的回調函數作為這個Request對象的回調函數
r = Request(url=link.url, callback=self._response_downloaded)
r.meta.update(rule=n, link_text=link.text)
#對每個Request調用process_request()函數。該函數默認為indentify,即不做任何處理,直接返回該Request.
yield rule.process_request(r)

#處理通過rule提取出的連接,并返回item以及request
def _response_downloaded(self, response):
rule = self._rules[response.meta['rule']]
return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow)

#解析response對象,會用callback解析處理他,并返回request或Item對象
def _parse_response(self, response, callback, cb_kwargs, follow=True):
#首先判斷是否設置了回調函數。(該回調函數可能是rule中的解析函數,也可能是 parse_start_url函數)
#如果設置了回調函數(parse_start_url()),那么首先用parse_start_url()處理response對象,
#然后再交給process_results處理。返回cb_res的一個列表
if callback:
#如果是parse調用的,則會解析成Request對象
#如果是rule callback,則會解析成Item
cb_res = callback(response, **cb_kwargs) or ()
cb_res = self.process_results(response, cb_res)
for requests_or_item in iterate_spider_output(cb_res):
yield requests_or_item

#如果需要跟進,那么使用定義的Rule規則提取并返回這些Request對象
if follow and self._follow_links:
#返回每個Request對象
for request_or_item in self._requests_to_follow(response):
yield request_or_item

def _compile_rules(self):
def get_method(method):
if callable(method):
return method
elif isinstance(method, basestring):
return getattr(self, method, None)

self._rules = [copy.copy(r) for r in self.rules]
for rule in self._rules:
rule.callback = get_method(rule.callback)
rule.process_links = get_method(rule.process_links)
rule.process_request = get_method(rule.process_request)

def set_crawler(self, crawler):
super(CrawlSpider, self).set_crawler(crawler)
self._follow_links = crawler.settings.getbool('CRAWLSPIDER_FOLLOW_LINKS', True)
  • 通過下面的命令可以快速創建 CrawlSpider模板 的代碼:

scrapy genspider -t crawl 爬蟲文件 域名

  • CrawlSpider繼承于Spider類,除了繼承過來的屬性外(name、allow_domains),還提供了新的屬性和方法:
class XcfcrawlspiderSpider(CrawlSpider):
#爬蟲名稱
name = 'xcfCrawlSpider'
#設置允許爬取的域
allowed_domains = ['xiachufang.com']
#設置起始的url
start_urls = ['http://www.xiachufang.com/category/']
rules = (
Rule(
LinkExtractor(allow=r'.*?/category/\d+/'),
callback='parse_item',
follow=True,
process_links='check_category_url'
),
)

rules

  • CrawlSpider使用rules屬性來決定爬蟲的爬取規則,并將匹配后的url請求提交給引擎,完成后續的爬取工作。

  • 在rules中包含一個或多個Rule對象,每個Rule對爬取網站的動作定義了某種特定操作,比如提取當前相應內容里的特定鏈接,是否對提取的鏈接跟進爬取,對提交的請求設置回調函數等。

如果多個rule匹配了相同的鏈接,則根據規則在本集合中被定義的順序,第一個會被使用。
class scrapy.spiders.Rule(
    link_extractor,
    callback = None,
    cb_kwargs = None,
    follow = None,
    process_links = None,
    process_request = None
)
  • link_extractor:是一個Link Extractor對象,用于定義需要提取的鏈接。

  • callback: 從link_extractor中每獲取到鏈接得到Responses時,會調用參數所指定的值作為回調函數,該回調函數接收一個response作為其一個參數。

  • follow:是一個布爾(boolean)值,指定了根據該規則從response提取的鏈接是否需要跟進。如果callback為None,follow 默認設置為True ,否則默認為False。

  • process_links:指定spider中哪個的函數將會被調用,從link_extractor中獲取到鏈接列表時將會調用該函數。該方法主要用來過濾。

  • process_request:指定處理函數,根據該Rule提取到的每個Request時,該函數將會被調用,可以對Request進行處理,該函數必須返回Request或者None

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容