Scrapy 是一個開源和協做的框架,其最初是爲了頁面抓取 (更確切來講, 網絡抓取 )所設計的,使用它能夠以快速、簡單、可擴展的方式從網站中提取所需的數據。但目前Scrapy的用途十分普遍,可用於如數據挖掘、監測和自動化測試等領域,也能夠應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。html
所謂框架其實就是一個已經被集成了各類功能(高性能異步下載,隊列,分佈式,解析,持久化等)的具備很強通用性的項目模板。對於框架的學習,重點是要學習其框架的特性、各個功能的用法便可。
scrapy和requests、bs4的關係,能夠作以下類比:python
requests + bs4 => socket
scrapy框架 => djangolinux
Scrapy 是基於twisted框架開發而來,twisted是一個流行的事件驅動的python網絡框架。所以Scrapy使用了一種非阻塞(又名異步)的代碼來實現併發(基於Twisted實現單線程併發下載頁面)。也具有解析下載內容功能、幫助實現「遞歸」、幫助完成數據持久化(數據寫入硬盤或數據庫)、還具有一些擴展性功能(自定義組件)。web
引擎首先會將爬蟲文件中的起始url獲取,並提交到調度器中。若是須要從url中下載數據,則調度器會將url經過引擎提交給下載器,下載器根據url去下載指定內容(響應器)。下載好的數據會經過引擎移交給爬蟲文件,爬蟲文件能夠將下載的數據進行指定格式的解析。若是解析出的數據須要進行持久化存儲,則爬蟲文件會將解析好的數據經過引擎移交給管道進行持久化存儲。數據庫
一、安裝wheel pip3 install wheel # 安裝後,便支持經過wheel文件安裝軟件,wheel文件官網:https://www.lfd.uci.edu/~gohlke/pythonlibs 二、下載twisted(Scrapy基於twisted框架): http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 安裝twisted: 進入下載目錄,執行: pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl 三、下載並安裝pywin32: pip3 install pywin32 四、安裝scrapy pip3 install scrapy
pip3 install scrapy
切換到項目目錄後,執行建立項目的命令,爬蟲項目即建立成功。django
$ scrapy startproject firstPro(工程名稱)
project_name/ |--scrapy.cfg # 項目的主配置信息。(真正爬蟲相關的配置信息在settings.py文件中) |--project_name/ |--__init__.py |--items.py # 設置數據存儲模板,用於結構化數據,如Django的Model |--pipelines.py # 數據持久化處理 |--settings.py # 配置文件(通常修改這裏),如:遞歸的層數、併發數,延遲下載等 |--spiders/ # 爬蟲目錄,如:建立文件,編寫爬蟲解析規則 |--__init__.py
$ pwd /Users/hqs/ScrapyProjects/firstBlood $ scrapy genspider qiubai www.qiushibaike.com Created spider 'qiubai' using template 'basic' in module: firstBlood.spiders.qiubai
執行成功後,就能夠在項目的spiders目錄下找到新生成的爬蟲文件了。windows
1)建立爬蟲程序語法瀏覽器
scrapy genspider 應用名稱 爬取網頁的起始url
2)建立的爬蟲文件內容模板bash
# -*- coding: utf-8 -*- import scrapy class QiubaiSpider(scrapy.Spider): # Spider是全部爬蟲的父類 name = 'qiubai' # 爬蟲文件的名稱:經過爬蟲文件的名稱能夠指定定位到某一個具體的爬蟲文件 allowed_domains = ['www.qiushibaike.com'] # 容許的域名:只爬取指定域名下的頁面數據 start_urls = ['http://www.qiushibaike.com/'] # 起始url:當前工程將要爬取頁面對應的url def parse(self, response): """ 解析方法:對獲取的頁面數據進行指定內容解析 :param response: 根據起始url列表發起請求,請求成功返回的響應對象 :return: """ pass
# -*- coding: utf-8 -*- import scrapy class QiubaiSpider(scrapy.Spider): # Spider是全部爬蟲的父類 name = 'qiubai' # 爬蟲文件的名稱:經過爬蟲文件的名稱能夠指定定位到某一個具體的爬蟲文件 allowed_domains = ['www.qiushibaike.com'] # 容許的域名:只爬取指定域名下的頁面數據 start_urls = ['http://www.qiushibaike.com/'] # 起始url:當前工程將要爬取頁面對應的url def parse(self, response): """ 解析方法:對獲取的頁面數據進行指定內容解析 :param response: 根據起始url列表發起請求,請求成功返回的響應對象 :return: """ print(response.text) # 獲取字符串類型的響應內容 # print(response.body) # 獲取字節類型的相應內容 # 注意:parse方法的返回值必須是迭代器或空 # 未指定返回值時,返回值默認爲空
# Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' # 假裝請求載體身份 # Obey robots.txt rules ROBOTSTXT_OBEY = False # 不聽從門戶網站robots協議,避免某些信息爬取不到
注意:
(1)取消USER_AGENT註釋,這裏給它添加火狐瀏覽器身份標識,以假裝請求載體身份。
(2)將ROBOTSTXT_BOE修改成False,即不遵照門戶網站的robots協議,避免某些信息爬取不到。(這個可視狀況決定是否遵照)網絡
# scrapy crawl 應用名稱 --nolog(阻止日誌信息輸出) $ scrapy crawl qiubai
添加 '--nolog' 參數能夠阻止日誌信息的輸出,只輸出爬取的頁面數據。
需求:糗百中段子的內容和做者。
依然使用以前建立的項目,所以省略流程第一步的工程建立操做。
$ pwd /Users/hqs/ScrapyProjects/firstBlood $ scrapy genspider qiubaipro www.qiushibaike.com/text Created spider 'qiubaipro' using template 'basic' in module: firstBlood.spiders.qiubaipro
Scrapy已經集成好了xpath解析的接口,所以推薦使用xpath進行指定內容的解析。
Control-Shift-X開啓xpath插件。
import scrapy class QiubaiproSpider(scrapy.Spider): name = 'qiubaipro' # allowed_domains = ['www.qiushibaike.com/text'] # 圖片等信息可能不屬於指定域名之下 start_urls = ['https://www.qiushibaike.com/text/'] # 注意修改默認協議頭 def parse(self, response): # 建議使用xpath來執行指定內容的解析(Scrapy已經集成好了xpath解析的接口) # 段子的內容和做者 div_list = response.xpath('//div[@id="content-left"]/div') for div in div_list: # 經過xpath解析到的指定內容被存儲到了selector對象中 # 須要經過extract()方法來提取selector對象中存儲的數據值 # 方法一: # author = div.xpath('./div/a[2]/h2/text()').extract()[0] # './'表示解析當前局部div; a[2]表示第二個a標籤 # 方法二:extract_first()等同於extract()[0] author = div.xpath('./div/a[2]/h2/text()').extract_first() content = div.xpath('.//div[@class="content"]/span/text()').extract_first() # './/'表示當前局部全部元素;@class匹配類屬性 print(author)
注意:
1)第四步的修改配置文件也省略,配置方法見前面一節。
2)xpath解析的指定內容被存儲到了selector對象中。
3)能夠經過extract()方法來提取selector對象中存儲的數據值。
4)selector對象和extract方法
使用extract()方法前: [<Selector xpath='./div/a[2]/h2/text()' data='\n南九\n'>] [<Selector xpath='./div/a[2]/h2/text()' data='\n無書齋主\n'>] [<Selector xpath='./div/a[2]/h2/text()' data='\n請閉上眼睛裏\n'>] 使用extract()方法後: ['\n好吃的焦糖餅乾~\n'] ['\n艾瑪*^o^*ZW…\n'] ['\n嘻嘻嘻,一\n']
5)extract_first()等同於extract()[0]
# scrapy crawl 爬蟲名稱 :該種執行形式會顯示執行的日誌信息 # scrapy crawl 爬蟲名稱 --nolog:該種執行形式不會顯示執行的日誌信息 $ scrapy crawl qiubaipro --nolog