1. 程式人生 > >scrapy——3 crawlSpider

scrapy——3 crawlSpider

req name ofo 有時 pat 打印 spider 技術 extra

scrapy——3 crawlSpider

crawlSpider

  • 爬取一般網站常用的爬蟲類。其定義了一些規則(rule)來提供跟進link的方便的機制。
  • 也許該spider並不是完全適合您的特定網站或項目,但其對很多情況都使用。因此您可以以其為起點,根據需求修改部分方法。當然您也可以實現自己的spider。

技術分享圖片

  • CrawlSpider使用rules來決定爬蟲的爬取規則,並將匹配後的url請求提交給引擎。所以在正常情況下,CrawlSpider不需要單獨手動返回請求了。
  • 在rules中包含一個或多個Rule對象,每個Rule對爬取網站的動作定義了某種特定操作,比如提取當前相應內容裏的特定鏈接,是否對提取的鏈接跟進爬取,對提交的請求設置回調函數等。
  • 如果多個rule匹配了相同的鏈接,則根據規則在本集合中被定義的順序,第一個會被使用。

技術分享圖片

  • 技術分享圖片
  • link_extractor:是一個Link Extractor對象,用於定義需要提取的鏈接。
  • callback: 從link_extractor中每獲取到鏈接時,參數所指定的值作為回調函數,該回調函數接受一個response作為其第一個參數。
  • 註意:當編寫爬蟲規則時,避免使用parse作為回調函數。由於CrawlSpider使用parse方法來實現其邏輯,如果覆蓋了 parse方法,crawl spider將會運行失敗。
  • follow:是一個布爾(boolean)值,指定了根據該規則從response提取的鏈接是否需要跟進。 如果callback為None,follow 默認設置為True ,否則默認為False。
  • process_links:指定該spider中哪個的函數將會被調用,從link_extractor中獲取到鏈接列表時將會調用該函數。該方法主要用來過濾。
  • process_request:指定該spider中哪個的函數將會被調用, 該規則提取到每個request時都會調用該函數。 (用來過濾request)

技術分享圖片

技術分享圖片

實戰 愛問網站數據爬取

我們需要用crawlScrapy的規則匹配出每個問題的鏈接,對連接內的提問標題,和提問人進行爬取,以及匹配下一頁的url

前面講過scrapy shell ,可以在scrapy shell https://iask.sina.com.cn/c/1073.html

中,先進行匹配測試

先在scrapycrawl中導入LineExtractor再匹配,用extract_links(response)取出數據

In [1]: from scrapy.linkextractors import LinkExtractor
 
In [2]: page = LinkExtractor(allow=/c/1073-all-\d+-new\.html).extract_links(response) # 匹配下一頁url

In [3]: page
Out[3]:
[Link(url=https://iask.sina.com.cn/c/1073-all-180-new.html, text=2, fragment=‘‘, nofollow=False),
 Link(url=https://iask.sina.com.cn/c/1073-all-191-new.html, text=3, fragment=‘‘, nofollow=False),
.........
 Link(url=https://iask.sina.com.cn/c/1073-all-8608-new.html, text=20, fragment=‘‘, nofollow=False),
 Link(url=https://iask.sina.com.cn/c/1073-all-8618-new.html, text=30, fragment=‘‘, nofollow=False)]

In [4]: page = LinkExtractor(restrict_xpaths=//li[@class="list"]).extract_links(response) # 要獲取標題和提問人,需要先找到這個貼的url

In [5]: page
Out[5]:
[Link(url=https://iask.sina.com.cn/b/1SXKZurG8ST9.html, text=avg說獵殺潛航3主程序是backdoor.seed, fragment=‘‘, nofollow=False),
 Link(url=https://iask.sina.com.cn/b/1SWo9FvedMVJ.html, text=怎麽去掉關於應用程序錯誤的提示???, fragment=‘‘, nofollow=False),
 Link(url=https://iask.sina.com.cn/b/gWP5Ttnm8NDB.html, text=在超聲波測距儀的設計中用到了cx20106a,在protel中怎麽找不 到啊?, fragment=‘‘, nofollow=False),
 ..........

 Link(url=https://iask.sina.com.cn/b/87xMZOVEB3Dr.html, text=景德鎮哪家公司做網頁設計比較靠譜?有電話嗎?, fragment=‘‘, nofollow=False),
 Link(url=https://iask.sina.com.cn/b/87L5oCMvbsKB.html, text=景德鎮有專業的做網頁設計的公司嗎?, fragment=‘‘, nofollow=False)]

方便看的話還可以用.url提取出url

In [7]: page[0].url
Out[7]: https://iask.sina.com.cn/b/1SXKZurG8ST9.html

In [8]: page[1].url
Out[8]: https://iask.sina.com.cn/b/1SWo9FvedMVJ.html

In [9]: page[2].url
Out[9]: https://iask.sina.com.cn/b/gWP5Ttnm8NDB.html

隨便挑一個url繼續scrapy shell url解析我們需要的數據

scrapy shell https://iask.sina.com.cn/b/gWP5Ttnm8NDB.html

In [1]: question = response.xpath(//h2[@class="question-title "]/text()).extract_first()

In [2]: question
Out[2]: 在超聲波測距儀的設計中用到了cx20106a,在protel中怎麽找不到啊?

In [3]: ask_people = response.xpath(//span[@class="user-name"]/text()).extract_first()

In [4]: ask_people
Out[4]: 距離會產生美只有時間不要太長

準備完畢就可以開始寫代碼了

  • 先創建項目
  • 註意:crawl spider 創建項目方法略有不同 Scrapy genspider –t crawl “spider_name”“url”

技術分享圖片

  • IAsk\items.py 確定需要的數據
    # -*- coding: utf-8 -*-
    
    # Define here the models for your scraped items
    #
    # See documentation in:
    # https://doc.scrapy.org/en/latest/topics/items.html
    
    import scrapy
    
    
    class IaskItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        question_title = scrapy.Field()
        ask_name = scrapy.Field()
  • IAsk\settings.py 激活管道,以及設置忽略爬蟲協議(有些網站會設置爬蟲協議,禮貌式反爬,可無視)

技術分享圖片 技術分享圖片

  • IAsk\spiders\iask.py 編寫代碼
    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    
    from ..items import IaskItem
    
    
    class IaskSpider(CrawlSpider):
        name = iask
        allowed_domains = [iask.sina.com.cn]
        start_urls = [https://iask.sina.com.cn/c/1073.html]
    
        rules = (
            Rule(LinkExtractor(allow=/c/1073-all-\d+-new\.html), callback=parse_item, follow=True), # 設置規則匹配下一頁url,無需跳轉方法,此處只是打印出來看
            Rule(LinkExtractor(restrict_xpaths=//li[@class="list"]), callback=parse_item1, follow=True),  # 設置匹配每一個貼的url,再跳轉匹配問題和提問人
        )
    
        def parse_item(self, response):
            print(response.url,)
    
        def parse_item1(self, response):
            ask_item = IaskItem()  # 創建管道對象
            ask_item[question_title] = response.xpath(//h2[@class="question-title "]/text()).extract_first()
            ask_item[ask_name] = response.xpath(//span[@class="user-name"]/text()).extract_first()
            yield ask_item  # 將數據以字典形式傳給管道

  • IAsk\pipelines.py 在保存數據,json格式
    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    #
    # Don‘t forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    import json
    
    class IaskPipeline(object):
        def __init__(self):
            self.f = open(ask.json, w, encoding=utf-8)
    
        def start_spider(self):
            pass
    
        def process_item(self, item, spider):
            s = json.dumps(dict(item), ensure_ascii=False) + \n
            self.f.write(s)
            return item
    
        def close_spider(self):
            self.f.close()

  • 在scrapy——2中,實戰介紹的是scrapy spider 的實現方法,點此查看, 這裏展示crawl spider的方法,做個對比

技術分享圖片

scrapy——3 crawlSpider