寫一個爬蟲,須要作不少的事情。好比:發送網絡請求、數據解析、數據存儲、反反爬蟲機制(更換ip代理、設置請求頭等)、異步請求等。這些工做若是每次都要本身從零開始寫的話,比較浪費時間。所以Scrapy
把一些基礎的東西封裝好了,在他上面寫爬蟲能夠變的更加的高效(爬取效率和開發效率)。所以真正在公司裏,一些上了量的爬蟲,都是使用Scrapy
框架來解決。css
流程圖(1):
html
Scrapy Engine(引擎)
:Scrapy
框架的核心部分。負責在Spider
和ItemPipeline
、Downloader
、Scheduler
中間通訊、傳遞數據等。Spider(爬蟲)
:發送須要爬取的連接給引擎,最後引擎把其餘模塊請求回來的數據再發送給爬蟲,爬蟲就去解析想要的數據。這個部分是咱們開發者本身寫的,由於要爬取哪些連接,頁面中的哪些數據是咱們須要的,都是由程序員本身決定。Scheduler(調度器)
:負責接收引擎發送過來的請求,並按照必定的方式進行排列和整理,負責調度請求的順序等。Downloader(下載器)
:負責接收引擎傳過來的下載請求,而後去網絡上下載對應的數據再交還給引擎。Item Pipeline(管道)
:負責將Spider(爬蟲)
傳遞過來的數據進行保存。具體保存在哪裏,應該看開發者本身的需求。Downloader Middlewares(下載中間件)
:能夠擴展下載器和引擎之間通訊功能的中間件。Spider Middlewares(Spider中間件)
:能夠擴展引擎和爬蟲之間通訊功能的中間件。pip install scrapy
便可安裝。注意:python
- 在
ubuntu
上安裝scrapy
以前,須要先安裝如下依賴:sudo apt-get install python3-dev build-essential python3-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev
,而後再經過pip install scrapy
安裝。- 若是在
windows
系統下,提示這個錯誤ModuleNotFoundError: No module named 'win32api'
,那麼使用如下命令能夠解決:pip install pypiwin32
。
要使用Scrapy
框架建立項目,須要經過命令來建立。首先進入到你想把這個項目存放的目錄。而後使用如下命令建立:程序員
scrapy startproject [項目名稱]
如下介紹下主要文件的做用: 正則表達式
items
的模型存儲到本地磁盤中。 scrapy gensipder qsbk "qiushibaike.com"
建立了一個名字叫作qsbk
的爬蟲,而且能爬取的網頁只會限制在qiushibaike.com
這個域名下。shell
import scrapy class QsbkSpider(scrapy.Spider): name = 'qsbk' allowed_domains = ['qiushibaike.com'] start_urls = ['http://qiushibaike.com/'] def parse(self, response): pass
其實這些代碼咱們徹底能夠本身手動去寫,而不用命令。只不過是不用命令,本身寫這些代碼比較麻煩。
要建立一個Spider,那麼必須自定義一個類,繼承自scrapy.Spider
,而後在這個類中定義三個屬性和一個方法。 json
parse
方法。這個是個固定的寫法。這個方法的做用有兩個,第一個是提取想要的數據。第二個是生成下一個請求的url。settings.py
代碼:在作一個爬蟲以前,必定要記得修改setttings.py
中的設置。兩個地方是強烈建議設置的。 ubuntu
ROBOTSTXT_OBEY
設置爲False。默認是True。即遵照機器協議,那麼在爬蟲的時候,scrapy首先去找robots.txt文件,若是沒有找到。則直接中止爬取。 DEFAULT_REQUEST_HEADERS
添加User-Agent
。這個也是告訴服務器,我這個請求是一個正常的請求,不是一個爬蟲。爬蟲部分代碼:小程序
import scrapy from abcspider.items import QsbkItem class QsbkSpider(scrapy.Spider): name = 'qsbk' allowed_domains = ['qiushibaike.com'] start_urls = ['https://www.qiushibaike.com/text/'] def parse(self, response): outerbox = response.xpath("//div[@id='content-left']/div") items = [] for box in outerbox: author = box.xpath(".//div[contains(@class,'author')]//h2/text()").extract_first().strip() content = box.xpath(".//div[@class='content']/span/text()").extract_first().strip() item = QsbkItem() item["author"] = author item["content"] = content items.append(item) return items
items.py部分代碼:windows
import scrapy class QsbkItem(scrapy.Item): author = scrapy.Field() content = scrapy.Field()
pipeline部分代碼:
import json class AbcspiderPipeline(object): def __init__(self): self.items = [] def process_item(self, item, spider): self.items.append(dict(item)) print("="*40) return item def close_spider(self,spider): with open('qsbk.json','w',encoding='utf-8') as fp: json.dump(self.items,fp,ensure_ascii=False)
運行scrapy項目。須要在終端,進入項目所在的路徑,而後scrapy crawl [爬蟲名字]
便可運行指定的爬蟲。若是不想每次都在命令行中運行,那麼能夠把這個命令寫在一個文件中。之後就在pycharm中執行運行這個文件就能夠了。好比如今新建立一個文件叫作start.py
,而後在這個文件中填入如下代碼:
from scrapy import cmdline cmdline.execute("scrapy crawl qsbk".split())
在上一個糗事百科的爬蟲案例中。咱們是本身在解析完整個頁面後獲取下一頁的url,而後從新發送一個請求。有時候咱們想要這樣作,只要知足某個條件的url,都給我進行爬取。那麼這時候咱們就能夠經過CrawlSpider
來幫咱們完成了。CrawlSpider
繼承自Spider
,只不過是在以前的基礎之上增長了新的功能,能夠定義爬取的url的規則,之後scrapy碰到知足條件的url都進行爬取,而不用手動的yield Request
。
以前建立爬蟲的方式是經過scrapy genspider [爬蟲名字] [域名]
的方式建立的。若是想要建立CrawlSpider
爬蟲,那麼應該經過如下命令建立:
scrapy genspider -t crawl [爬蟲名字] [域名]
使用LinkExtractors
能夠不用程序員本身提取想要的url,而後發送請求。這些工做均可以交給LinkExtractors
,他會在全部爬的頁面中找到知足規則的url
,實現自動的爬取。如下對LinkExtractors
類作一個簡單的介紹:
class scrapy.linkextractors.LinkExtractor( allow = (), deny = (), allow_domains = (), deny_domains = (), deny_extensions = None, restrict_xpaths = (), tags = ('a','area'), attrs = ('href'), canonicalize = True, unique = True, process_value = None )
主要參數講解:
定義爬蟲的規則類。如下對這個類作一個簡單的介紹:
class scrapy.spiders.Rule( link_extractor, callback = None, cb_kwargs = None, follow = None, process_links = None, process_request = None )
主要參數講解:
LinkExtractor
對象,用於定義爬取規則。CrawlSpider
使用了parse
做爲回調函數,所以不要覆蓋parse
做爲回調函數本身的回調函數。咱們想要在爬蟲中使用xpath、beautifulsoup、正則表達式、css選擇器等來提取想要的數據。可是由於scrapy
是一個比較重的框架。每次運行起來都要等待一段時間。所以要去驗證咱們寫的提取規則是否正確,是一個比較麻煩的事情。所以Scrapy
提供了一個shell,用來方便的測試規則。固然也不只僅侷限於這一個功能。
打開cmd終端,進入到Scrapy
項目所在的目錄,而後進入到scrapy
框架所在的虛擬環境中,輸入命令scrapy shell [連接]
。就會進入到scrapy的shell環境中。在這個環境中,你能夠跟在爬蟲的parse
方法中同樣使用了。
第五節:Request 和Response
第六節:下載文件和圖片
第七節:Downloader Middlewares(下載器中間件):
from scrapy import signals import random class UserAgentDownloadMiddleware(object): USER_AGENTS = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1'
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50' ] def process_request(self,request,spider): user_agent = random.choice(self.USER_AGENTS) # 隨機選擇一個請求頭 request.headers['User-Agent'] = user_agent
請求頭獲取網站:www.useragentstring.com 或者 http://www.jsons.cn/useragent/
ip代理池中間件
在如下代理商中購買代理:
1,芝麻代理:http://http.zhimadaili.com/
2,太陽代理:http://http.taiyangdaili.com/
3,快代理:http://http.kuaidaili.com/
4,訊代理:http://http.xdaili.com/
5,螞蟻代理:http://http.mayidaili.com/
等購買代理。
使用ip代理池:
示例代碼以下:
# 開放代理池設置 class IPProxyDownloadMiddleware(object): PROXIES = ["178.44.170.153:8080", "110.44.113.182:8080", "209.126.124.73:8888"] def process_request(self, request, spider): proxy = random.choice(self.PROXIES) request.meta['proxy'] = proxy
import base64
#獨享代理池設置 class IPProxyDownloadMiddleware(object): def process_request(self, request, spider): proxy = '121.199.6.124:16816' user_password = "970138074:rxcd35fd" request.meta['proxy'] = proxy #bytes b64_user_password = base64.b64encode(user_password.encode('utf-8')) request.headers['Proxy-Authorization'] = 'basic ' + b64_user_password.decode('utf-8')