scrapy——3 crawlSpider
阿新 • • 發佈:2018-11-10
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