爬蟲課堂(二十五)|使用CrawlSpider习贫、LinkExtractors逛球、Rule進(jìn)行全站爬取

爬蟲課堂(二十二)|使用LinkExtractor提取鏈接中講解了LinkExtractor的使用,本章節(jié)來講解使用CrawlSpider+LinkExtractor+Rule進(jìn)行全站爬取苫昌。
一颤绕、CrawlSpider介紹
Scrapy框架中分兩類爬蟲,Spider類和CrawlSpider類祟身。Spider類的使用已經(jīng)講解了很多奥务,但是如果想爬取某個(gè)網(wǎng)站的全站信息的話,CrawlSpider類是個(gè)非常不錯(cuò)的選擇袜硫。CrawlSpider繼承于Spider類氯葬,CrawlSpider是爬取那些具有一定規(guī)則網(wǎng)站的常用爬蟲,可以說它是為全站爬取而生父款。
它除了繼承過來的屬性(name溢谤、allow_domains)外,還提供了新的屬性和方法:
1.1憨攒、LinkExtractors
class scrapy.linkextractors.LinkExtractor
Link Extractors 的目的很簡(jiǎn)單:提取鏈接世杀。每個(gè)Link Extractor有唯一的公共方法是 extract_links(),它接收一個(gè) Response 對(duì)象肝集,并返回一個(gè) scrapy.link.Link 對(duì)象瞻坝。
Link Extractors要實(shí)例化一次,并且 extract_links()方法會(huì)根據(jù)不同的 Response 調(diào)用多次提取鏈接?
主要參數(shù)如下:

  • allow:滿足括號(hào)中“正則表達(dá)式”的值會(huì)被提取杏瞻,如果為空所刀,則全部匹配衙荐。
  • deny:與這個(gè)正則表達(dá)式(或正則表達(dá)式列表)不匹配的URL一定不提取。
  • allow_domains:會(huì)被提取的鏈接的domains浮创。
  • deny_domains:一定不會(huì)被提取鏈接的domains忧吟。
  • restrict_xpaths:使用XPath表達(dá)式,和allow共同作用過濾鏈接斩披。

關(guān)于Link Extractors如何使用可以參考爬蟲課堂(二十二)|使用LinkExtractor提取鏈接這篇文章溜族。
1.2、rules
在rules中包含一個(gè)或多個(gè)Rule對(duì)象垦沉,每個(gè)Rule對(duì)爬取網(wǎng)站的動(dòng)作定義了特定操作煌抒。如果多個(gè)Rule匹配了相同的鏈接,則根據(jù)規(guī)則在本集合中被定義的順序厕倍,第一個(gè)會(huì)被使用寡壮。
Rule類的定義如下:

class scrapy.contrib.spiders.
Rule
(link_extractor,callback=None,cb_kwargs=None,follow=None,process_links=None,process_request=None)

主要參數(shù)如下:

  • link_extractor:是一個(gè)Link Extractor對(duì)象。其定義了如何從爬取到的頁面提取鏈接讹弯。
  • callback:是一個(gè)callable或string(該Spider中同名的函數(shù)將會(huì)被調(diào)用)况既。從link_extractor中每獲取到鏈接時(shí)將會(huì)調(diào)用該函數(shù)。該回調(diào)函數(shù)接收一個(gè)response作為其第一個(gè)參數(shù)闸婴,并返回一個(gè)包含Item以及Request對(duì)象(或者這兩者的子類)的列表坏挠。
  • cb_kwargs:包含傳遞給回調(diào)函數(shù)的參數(shù)(keyword argument)的字典芍躏。
  • follow:是一個(gè)boolean值邪乍,指定了根據(jù)該規(guī)則從response提取的鏈接是否需要跟進(jìn)。如果callback為None对竣,follow默認(rèn)設(shè)置True庇楞,否則默認(rèn)False。
  • process_links:是一個(gè)callable或string(該Spider中同名的函數(shù)將會(huì)被調(diào)用)否纬。從link_extrator中獲取到鏈接列表時(shí)將會(huì)調(diào)用該函數(shù)吕晌。該方法主要是用來過濾。
  • process_request:是一個(gè)callable或string(該spider中同名的函數(shù)都將會(huì)被調(diào)用)临燃。該規(guī)則提取到的每個(gè)request時(shí)都會(huì)調(diào)用該函數(shù)睛驳。該函數(shù)必須返回一個(gè)request或者None。用來過濾request膜廊。

二乏沸、CrawlSpider使用
假設(shè)我們要爬取簡(jiǎn)書的所有用戶的信息(用戶名稱、關(guān)注數(shù)爪瓜、粉絲數(shù)蹬跃、文章數(shù)、字?jǐn)?shù)铆铆、收獲喜歡數(shù))蝶缀,如下圖25-1所示的用戶主頁:

圖25-1

用戶的主頁地址為http://www.reibang.com/u/c34455009dd8
2.1丹喻、定義Item文件

from scrapy.item import Item, Field

# 簡(jiǎn)書的全站用戶信息
class JianshuUserItem(Item):
    # 用戶名稱
    name = Field()
    # 關(guān)注數(shù)
    followNumber = Field()
    # 粉絲數(shù)
    fansNumber = Field()
    # 文章數(shù)
    articleNumber = Field()
    # 字?jǐn)?shù)
    wordCount = Field()
    # 收獲喜歡數(shù)
    likeNumber = Field()

2.2、定義pipeline文件

import json
# 設(shè)置字符集翁都,防止編碼參數(shù)出錯(cuò)
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
from scrapy.exporters import JsonItemExporter

class DataSubmitJsonFilePipeline(object):
    def __init__(self):
        self.file = open('jianshu.json', 'wb')

    # 把item寫入JSON文件
    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + "\n"
        self.file.write(line)
        return item

    def close_spider(self, spider):
        self.file.close()

2.3碍论、定義setting文件

ITEM_PIPELINES = {
    'tutorial.pipelines.DataSubmitJsonFilePipeline': 1,
}

2.4、編寫spider文件
首先需要找出用戶個(gè)人主頁鏈接的通用字符柄慰,從http://www.reibang.com/u/c34455009dd8及更多的其他用戶個(gè)人主頁URL分析得知通用字符為/u/骑冗。

# response中提取鏈接的匹配規(guī)則,得出符合條件的鏈接
pattern = '.*/u/*.'
pagelink = LinkExtractor(allow=pattern)

分析個(gè)人主頁的HTML代碼先煎,得知用戶的用戶名稱贼涩、關(guān)注數(shù)、粉絲數(shù)薯蝎、文章數(shù)遥倦、字?jǐn)?shù)、收獲喜歡數(shù)等字段都是在//div[@class='main-top']中占锯,如下圖25-2所示:

圖25-2

進(jìn)一步分析HTML袒哥,如下圖25-3所示:
圖25-3

編寫提取用戶名稱、關(guān)注數(shù)消略、粉絲數(shù)堡称、文章數(shù)、字?jǐn)?shù)艺演、收獲喜歡數(shù)等值的代碼如下:

# 用戶名稱
item['name'] = each.xpath("./div[@class='title']/a/text()").extract()[0]
# 關(guān)注數(shù)
item['followNumber'] = each.xpath("./div[@class='info']/ul/li[1]//a/p/text()").extract()[0]
# 粉絲數(shù)
item['fansNumber'] = each.xpath("./div[@class='info']/ul/li[2]//a/p/text()").extract()[0]
# 文章數(shù)
item['articleNumber'] = each.xpath("./div[@class='info']/ul/li[3]//a/p/text()").extract()[0]
# 字?jǐn)?shù)
item['wordCount'] = each.xpath("./div[@class='info']/ul/li[4]//p/text()").extract()[0]
# 收獲喜歡數(shù)
item['likeNumber'] = each.xpath("./div[@class='info']/ul/li[5]//p/text()").extract()[0]

最后完整代碼如下:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# **********************************************************
# * Author        : huangtao
# * Email         : huangtao@yimian.me
# * Create time   : 2018/4/1 下午6:34
# * Last modified : 2018/4/1 下午6:34
# * Filename      : jianshu_spider_crawl.py
# * Description   : 
# **********************************************************

# 導(dǎo)入鏈接匹配規(guī)則類却紧,用來提取符合規(guī)則的鏈接
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from tutorial.items import JianshuUserItem

class JianshuCrawl(CrawlSpider):
    name = "jianshu_spider_crawl"
    # 可選,加上會(huì)有一個(gè)爬取的范圍
    allowed_domains = ["jianshu.com"]
    start_urls = ['http://www.reibang.com/']

    # response中提取鏈接的匹配規(guī)則胎撤,得出符合條件的鏈接
    pattern = '.*jianshu.com/u/*.'
    pagelink = LinkExtractor(allow=pattern)

    # 可以寫多個(gè)rule規(guī)則
    rules = [
        # 只要符合匹配規(guī)則晓殊,在rule中都會(huì)發(fā)送請(qǐng)求,同時(shí)調(diào)用回調(diào)函數(shù)處理響應(yīng)伤提。
        # rule就是批量處理請(qǐng)求巫俺。
        Rule(pagelink, callback='parse_item', follow=True),
    ]

    # 不能寫parse方法,因?yàn)樵创a中已經(jīng)有了肿男,會(huì)覆蓋導(dǎo)致程序不能跑
    def parse_item(self, response):
        for each in response.xpath("http://div[@class='main-top']"):
            item = JianshuUserItem()
            # 用戶名稱
            item['name'] = each.xpath("./div[@class='title']/a/text()").extract()[0]
            # 關(guān)注數(shù)
            item['followNumber'] = each.xpath("./div[@class='info']/ul/li[1]//a/p/text()").extract()[0]
            # 粉絲數(shù)
            item['fansNumber'] = each.xpath("./div[@class='info']/ul/li[2]//a/p/text()").extract()[0]
            # 文章數(shù)
            item['articleNumber'] = each.xpath("./div[@class='info']/ul/li[3]//a/p/text()").extract()[0]
            # 字?jǐn)?shù)
            item['wordCount'] = each.xpath("./div[@class='info']/ul/li[4]//p/text()").extract()[0]
            # 收獲喜歡數(shù)
            item['likeNumber'] = each.xpath("./div[@class='info']/ul/li[5]//p/text()").extract()[0]

            # 把數(shù)據(jù)交給管道文件
            yield item
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末介汹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子舶沛,更是在濱河造成了極大的恐慌嘹承,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冠王,死亡現(xiàn)場(chǎng)離奇詭異赶撰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門豪娜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來餐胀,“玉大人,你說我怎么就攤上這事瘤载》裨郑” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我利赋,道長(zhǎng)吓歇,這世上最難降的妖魔是什么路操? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘崭别。我一直安慰自己,他們只是感情好恐锣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布茅主。 她就那樣靜靜地躺著,像睡著了一般土榴。 火紅的嫁衣襯著肌膚如雪诀姚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天玷禽,我揣著相機(jī)與錄音赫段,去河邊找鬼。 笑死论衍,一個(gè)胖子當(dāng)著我的面吹牛瑞佩,可吹牛的內(nèi)容都是我干的聚磺。 我是一名探鬼主播坯台,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瘫寝!你這毒婦竟也來了蜒蕾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤焕阿,失蹤者是張志新(化名)和其女友劉穎咪啡,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暮屡,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撤摸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片准夷。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钥飞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衫嵌,到底是詐尸還是另有隱情读宙,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布楔绞,位于F島的核電站结闸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏酒朵。R本人自食惡果不足惜桦锄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔫耽。 院中可真熱鬧察纯,春花似錦、人聲如沸针肥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慰枕。三九已至具则,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間具帮,已是汗流浹背博肋。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜂厅,地道東北人匪凡。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像掘猿,于是被迫代替她去往敵國(guó)和親病游。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容