網絡爬蟲第五章之Scrapy框架

 

第一節:Scrapy框架架構

Scrapy框架介紹

寫一個爬蟲,須要作不少的事情。好比:發送網絡請求、數據解析、數據存儲、反反爬蟲機制(更換ip代理、設置請求頭等)、異步請求等。這些工做若是每次都要本身從零開始寫的話,比較浪費時間。所以Scrapy把一些基礎的東西封裝好了,在他上面寫爬蟲能夠變的更加的高效(爬取效率和開發效率)。所以真正在公司裏,一些上了量的爬蟲,都是使用Scrapy框架來解決。css

Scrapy架構圖:

  1. 流程圖(1):

    html

Scrapy框架模塊功能:

  1. Scrapy Engine(引擎)Scrapy框架的核心部分。負責在SpiderItemPipelineDownloaderScheduler中間通訊、傳遞數據等。
  2. Spider(爬蟲):發送須要爬取的連接給引擎,最後引擎把其餘模塊請求回來的數據再發送給爬蟲,爬蟲就去解析想要的數據。這個部分是咱們開發者本身寫的,由於要爬取哪些連接,頁面中的哪些數據是咱們須要的,都是由程序員本身決定。
  3. Scheduler(調度器):負責接收引擎發送過來的請求,並按照必定的方式進行排列和整理,負責調度請求的順序等。
  4. Downloader(下載器):負責接收引擎傳過來的下載請求,而後去網絡上下載對應的數據再交還給引擎。
  5. Item Pipeline(管道):負責將Spider(爬蟲)傳遞過來的數據進行保存。具體保存在哪裏,應該看開發者本身的需求。
  6. Downloader Middlewares(下載中間件):能夠擴展下載器和引擎之間通訊功能的中間件。
  7. Spider Middlewares(Spider中間件):能夠擴展引擎和爬蟲之間通訊功能的中間件。

第二節:Scrapy快速入門

安裝和文檔:

  1. 安裝:經過pip install scrapy便可安裝。
  2. Scrapy官方文檔:http://doc.scrapy.org/en/latest
  3. Scrapy中文文檔:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html

注意:python

  1. 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安裝。
  2. 若是在windows系統下,提示這個錯誤ModuleNotFoundError: No module named 'win32api',那麼使用如下命令能夠解決:pip install pypiwin32

快速入門:

建立項目:

要使用Scrapy框架建立項目,須要經過命令來建立。首先進入到你想把這個項目存放的目錄。而後使用如下命令建立:程序員

scrapy startproject [項目名稱]

目錄結構介紹:


如下介紹下主要文件的做用: 正則表達式

  1. items.py:用來存放爬蟲爬取下來數據的模型。
  2. middlewares.py:用來存放各類中間件的文件。
  3. pipelines.py:用來將items的模型存儲到本地磁盤中。
  4. settings.py:本爬蟲的一些配置信息(好比請求頭、多久發送一次請求、ip代理池等)。
  5. scrapy.cfg:項目的配置文件。
  6. spiders包:之後全部的爬蟲,都是存放到這個裏面。

使用Scrapy框架爬取糗事百科段子:

使用命令建立一個爬蟲:

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

  1. name:這個爬蟲的名字,名字必須是惟一的。
  2. allow_domains:容許的域名。爬蟲只會爬取這個域名下的網頁,其餘不是這個域名下的網頁會被自動忽略。
  3. start_urls:爬蟲從這個變量中的url開始。
  4. parse:引擎會把下載器下載回來的數據扔給爬蟲解析,爬蟲再把數據傳給這個parse方法。這個是個固定的寫法。這個方法的做用有兩個,第一個是提取想要的數據。第二個是生成下一個請求的url。

修改settings.py代碼

在作一個爬蟲以前,必定要記得修改setttings.py中的設置。兩個地方是強烈建議設置的。 ubuntu

  1. ROBOTSTXT_OBEY設置爲False。默認是True。即遵照機器協議,那麼在爬蟲的時候,scrapy首先去找robots.txt文件,若是沒有找到。則直接中止爬取。
  2. DEFAULT_REQUEST_HEADERS添加User-Agent。這個也是告訴服務器,我這個請求是一個正常的請求,不是一個爬蟲。

完成的爬蟲代碼

  1. 爬蟲部分代碼:小程序

    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

     

  2. items.py部分代碼:windows

     import scrapy
     class QsbkItem(scrapy.Item):
         author = scrapy.Field()
         content = scrapy.Field()

     

  3. 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項目。須要在終端,進入項目所在的路徑,而後scrapy crawl [爬蟲名字]便可運行指定的爬蟲。若是不想每次都在命令行中運行,那麼能夠把這個命令寫在一個文件中。之後就在pycharm中執行運行這個文件就能夠了。好比如今新建立一個文件叫作start.py,而後在這個文件中填入如下代碼:

from scrapy import cmdline

cmdline.execute("scrapy crawl qsbk".split())

 

第三節:CrawlSpider

在上一個糗事百科的爬蟲案例中。咱們是本身在解析完整個頁面後獲取下一頁的url,而後從新發送一個請求。有時候咱們想要這樣作,只要知足某個條件的url,都給我進行爬取。那麼這時候咱們就能夠經過CrawlSpider來幫咱們完成了。CrawlSpider繼承自Spider,只不過是在以前的基礎之上增長了新的功能,能夠定義爬取的url的規則,之後scrapy碰到知足條件的url都進行爬取,而不用手動的yield Request

CrawlSpider爬蟲:

建立CrawlSpider爬蟲:

以前建立爬蟲的方式是經過scrapy genspider [爬蟲名字] [域名]的方式建立的。若是想要建立CrawlSpider爬蟲,那麼應該經過如下命令建立:

scrapy genspider -t crawl [爬蟲名字] [域名]

 

LinkExtractors連接提取器:

使用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
)

 

主要參數講解:

  • allow:容許的url。全部知足這個正則表達式的url都會被提取。
  • deny:禁止的url。全部知足這個正則表達式的url都不會被提取。
  • allow_domains:容許的域名。只有在這個裏面指定的域名的url纔會被提取。
  • deny_domains:禁止的域名。全部在這個裏面指定的域名的url都不會被提取。
  • restrict_xpaths:嚴格的xpath。和allow共同過濾連接。

Rule規則類:

定義爬蟲的規則類。如下對這個類作一個簡單的介紹:

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

 

主要參數講解:

  • link_extractor:一個LinkExtractor對象,用於定義爬取規則。
  • callback:知足這個規則的url,應該要執行哪一個回調函數。由於CrawlSpider使用了parse做爲回調函數,所以不要覆蓋parse做爲回調函數本身的回調函數。
  • follow:指定根據該規則從response中提取的連接是否須要跟進。
  • process_links:從link_extractor中獲取到連接後會傳遞給這個函數,用來過濾不須要爬取的連接。

 

第四節:Scrapy Shell

咱們想要在爬蟲中使用xpath、beautifulsoup、正則表達式、css選擇器等來提取想要的數據。可是由於scrapy是一個比較重的框架。每次運行起來都要等待一段時間。所以要去驗證咱們寫的提取規則是否正確,是一個比較麻煩的事情。所以Scrapy提供了一個shell,用來方便的測試規則。固然也不只僅侷限於這一個功能。

打開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')
相關文章
相關標籤/搜索