1. 程式人生 > >scrapy 框架入門

scrapy 框架入門

執行流程

官網:https://docs.scrapy.org/en/latest/intro/overview.html

流程圖如下:
image.png

元件

1、引擎(EGINE):負責控制系統所有元件之間的資料流,並在某些動作發生時觸發事件。有關詳細資訊,請參見上面的資料流部分;

2、排程器(SCHEDULER):用來接受引擎發過來的請求, 壓入佇列中, 並在引擎再次請求的時候返回. 可以想像成一個URL的優先順序佇列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址;

3、下載器(DOWLOADER):用於下載網頁內容,並將網頁內容返回給EGINE,下載器是建立在twisted這個高效的非同步模型上的;

4、爬蟲(SPIDERS):SPIDERS是開發人員自定義的類,用來解析responses,並且提取items,或者傳送新的請求;

5、專案管道(ITEM PIPLINES):在items被提取後負責處理它們,主要包括清理、驗證、持久化(比如存到資料庫)等操作;

6、下載器中介軟體(Downloader Middlewares):位於Scrapy引擎和下載器之間,主要用來處理從EGINE傳到DOWLOADER的請求request,以及從DOWNLOADER傳到EGINE的響應response,可用該中介軟體做以下幾件事:

1、process a request just before it is sent to the Downloader (i.e. right before Scrapy sends the request to the website);
2、change received response before passing it to a spider;
3、send a new Request instead of passing received response to a spider;
4、pass response to a spider without fetching a web page;
5、silently drop some requests.
7、爬蟲中介軟體(Spider Middlewares):位於EGINE和SPIDERS之間,主要工作是處理SPIDERS的輸入(即responses)和輸出(即requests)

安裝

# Linux平臺
pip3 install scrapy

命令引數

# 檢視幫助
scrapy -h
scrapy <command> -h


Global commands:    # 全域性命令
    startproject    # 建立專案,會在當前目錄下建立專案資料夾
    
    genspider       # cd 進入專案目錄,建立爬蟲程式
        scrapy genspider baidu_spider www.baidu.com
            # 就會在spider目錄下生成 baidu_spider.py 檔案
    
    settings        # 如果是在專案目錄下,則得到的是該專案的配置
        > scrapy settings --get=SPIDER_MODULES
        ['first_crawl.spiders']

    runspider       # 執行一個獨立的python檔案,不必建立專案
        ROBOTSTXT_OBEY = False
        scrapy runspider  baidu_spider.py的絕對路徑

    shell           # scrapy shell url地址  在互動式除錯,如選擇器規則正確與否
        scrapy shell https://www.baidu.com/
        # 進入互動環境後,可執行命令:
            response.text           # 文字內容
            response.body           # 二進位制內容
            view(response)          # 開啟瀏覽器檢視響應頁面,已下載到本地
            response.css('a')       # 查詢所有a標籤
            response.xpath('//a')   # 查詢所有a標籤
            quit()                  # 退出互動環境 

    fetch           # 獨立於程單純地爬取一個頁面,可以拿到請求頭
        scrapy fetch https://www.baidu.com/  # 直接獲取所有資訊,類似shell但沒有互動除錯
        
    view            # 下載完畢後直接彈出瀏覽器,以此可以分辨出哪些資料是ajax請求
        
    version         # scrapy version 檢視scrapy的版本
    
    scrapy version  # -v檢視scrapy依賴庫的版本



Project-only commands:  # 必須切到專案資料夾下才能執行
    crawl           # 執行爬蟲,必須建立專案才行,確保配置檔案中ROBOTSTXT_OBEY=False
        scrapy crawl baidu_spider  # 此處爬蟲名稱為name屬性對應的爬蟲
    
    check           # 檢測專案中有無語法錯誤
    
    list            # 列出專案中所包含的爬蟲名
    
    parse           # scrapy parse url地址 --callback 回撥函式,以此可以驗證我們的回撥函式是否正確
    
    bench           # scrapy bentch壓力測試,檢測每分鐘能爬取的網頁數


# 官網連結
    https://docs.scrapy.org/en/latest/topics/commands.html

專案結構

project_name/
   scrapy.cfg
   project_name/
       __init__.py
       items.py
       pipelines.py
       settings.py
       spiders/
           __init__.py
           爬蟲1.py
           爬蟲2.py
           爬蟲3.py
  • 檔案說明:
  1. scrapy.cfg:專案的主配置資訊,用來部署scrapy時使用,爬蟲相關的配置資訊在·settings.py·檔案中;
  2. items.py:設定資料儲存模板,用於結構化資料,如:Django的Model;
  3. pipelines:資料處理行為,如:一般結構化的資料持久化
  4. settings.py:配置檔案,如:遞迴的層數、併發數,延遲下載等。強調:配置檔案的選項必須大寫否則視為無效,正確寫法USER_AGENT='xxxx';
  5. spiders:爬蟲目錄,如:建立檔案,編寫爬蟲規則。

選擇器xpath & css

測試網址:https://doc.scrapy.org/en/latest/_static/selectors-sample1.html
目標頁面內容:

<html>
 <head>
  <base href='http://example.com/' />
  <title>Example website</title>
 </head>
 <body>
  <div id='images'>
   <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>
   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>
   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>
   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>
   <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>
  </div>
 </body>
</html>

進入互動環境測試選擇器使用:

scrapy shell https://doc.scrapy.org/en/latest/_static/selectors-sample1.html
# 進入互動環境
# response.selector.css()或.xpath返回的是selector物件,再呼叫extract()和extract_first()從selector物件中解析出內容。
獲取標籤物件 // & /

/僅限於子標籤:

# 查詢目標頁面所有a標籤下的img子標籤
>>> response.xpath('//a/img').extract()
['<img src="image1_thumb.jpg">', '<img src="image2_thumb.jpg">', 
    '<img src="image3_thumb.jpg">', '<img src="image4_thumb.jpg">', '<img src="image5_thumb.jpg">']
    
    
>>> response.css('a img').extract()  # 返回物件列表


>>> response.css('a img').extract_first()  # 返回第一個標籤物件
'<img src="image1_thumb.jpg">'

//在子孫標籤中查詢:

# 查詢目標頁面所有的div標籤內容的所有img標籤
>>> response.xpath('//div//img').extract()
['<img src="image1_thumb.jpg">', '<img src="image2_thumb.jpg">', '<img src="image3_thumb.jpg">', '<img src="image4_thumb.jpg">', '<img src="image5_thumb.jpg">']
獲取標籤中的文字text
>>> response.css('a::text').extract()
['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ', 'Name: My image 4 ', 'Name: My image 5 ']


>>> response.xpath('//div/a/text()').extract()
['Name: My image 1 ', 'Name: My image 2 ', 'Name: My image 3 ', 
    'Name: My image 4 ', 'Name: My image 5 ']
獲取標籤屬性
# xpath獲取a標籤內的所有img的src屬性
>>> response.xpath('//a//img/@src').extract()
['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']


## css獲取屬性
>>> response.css('img::attr(src)').extract()
['image1_thumb.jpg', 'image2_thumb.jpg', 'image3_thumb.jpg', 'image4_thumb.jpg', 'image5_thumb.jpg']
巢狀查詢
>>> response.xpath('//div').css('a').xpath('@href').extract_first()
'image1.html'
設定預設值
>>> response.xpath("//div[@id='asas']").extract_first(default='not found')
'not found'
按照屬性查詢
# 查詢所有包含[href='image2.html']的標籤
>>> response.xpath("//*[@href='image2.html']").extract_first()
'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'


>>> response.css('#images [href="image2.html"]').extract_first()
'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'
模糊匹配
>>> response.css('#images [href*="image2"]').extract_first()
'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>'


>>> response.xpath('//a[contains(@href,"image1")]').extract_first()
'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>'
>>> response.xpath('//*[contains(@href,"image1")]').extract_first()
'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>'
正則表示式
# 先找到所有a標籤的文字selecor物件,然後逐個用re進行匹配,直到找到匹配的
>>> response.xpath('//a').re(".*My image 1 ")[0]
'<a href="image1.html">Name: My image 1 '