scrapy中的selenium

Bound_w發表於2019-03-04

引入

  • 在通過scrapy框架進行某些網站資料爬取的時候,往往會碰到頁面動態資料載入的情況發生,如果直接使用scrapy對其url發請求,是絕對獲取不到那部分動態載入出來的資料值。但是通過觀察我們會發現,通過瀏覽器進行url請求傳送則會載入出對應的動態載入出的資料。那麼如果我們想要在scrapy也獲取動態載入出的資料,則必須使用selenium建立瀏覽器物件,然後通過該瀏覽器物件進行請求傳送,獲取動態載入的資料值。

1.案例分析:

    - 需求:爬取網易新聞的國內板塊下的新聞資料

    - 需求分析:當點選國內超鏈進入國內對應的頁面時,會發現當前頁面展示的新聞資料是被動態載入出來的,如果直接通過程式對url進行請求,是獲取不到動態載入出的新聞資料的。則就需要我們使用selenium例項化一個瀏覽器物件,在該物件中進行url的請求,獲取動態載入的新聞資料。

2.selenium在scrapy中使用的原理分析:

當引擎將國內板塊url對應的請求提交給下載器後,下載器進行網頁資料的下載,然後將下載到的頁面資料,封裝到response中,提交給引擎,引擎將response在轉交給Spiders。Spiders接受到的response物件中儲存的頁面資料裡是沒有動態載入的新聞資料的。要想獲取動態載入的新聞資料,則需要在下載中介軟體中對下載器提交給引擎的response響應物件進行攔截,切對其內部儲存的頁面資料進行篡改,修改成攜帶了動態載入出的新聞資料,然後將被篡改的response物件最終交給Spiders進行解析操作。

3.selenium在scrapy中的使用流程:

    1.在spider的構造方法中建立一個瀏覽器物件(作為當前spider的一個屬性)
    2.重寫spider的一個方法closed(self,spider),在該方法中執行瀏覽器關閉的操作
    3.在下載中介軟體的process_response方法中,通過spider引數獲取瀏覽器物件
    4.在中介軟體的process_response中定製基於瀏覽器自動化的操作程式碼(獲取動態載入出來的頁面原始碼資料)
    5.例項化一個響應物件,且將page_source返回的頁面原始碼封裝到該物件中
    6.返回該新的響應物件

4.程式碼:

爬蟲程式碼:

import scrapy
from selenium import webdriver

class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://war.163.com/']
    def __init__(self):
        self.bro = webdriver.Chrome(executable_path=r'F:\上課作業視訊\爬蟲\s15day137爬蟲\chromedriver.exe')
    def parse(self, response):
        div_list = response.xpath('//div[@class="data_row news_article clearfix "]')
        for div in div_list:
            title = div.xpath('.//div[@class="news_title"]/h3/a/text()').extract_first()
            print(title)
    def closed(self,spider):
        print('關閉瀏覽器物件!')
        self.bro.quit()

middlewares.py

from scrapy import signals
from scrapy.http import HtmlResponse
from time import sleep   

 def process_response(self, request, response, spider):
        # Called with the response returned from the downloader.

        # Must either;
        # - return a Response object
        # - return a Request object
        # - or raise IgnoreRequest
        print('即將返回一個新的響應物件!!!')
        #獲取動態載入出來的資料
        bro = spider.bro
        bro.get(url=request.url)
        sleep(3)
        #包含了動態載入出來的新聞資料
        page_text = bro.page_source
        sleep(3)
        return HtmlResponse(url=spider.bro.current_url,body=page_text,encoding='utf-8',request=request)

settings配置

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'
ROBOTSTXT_OBEY = False
DOWNLOADER_MIDDLEWARES = {
   'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,
}
LOG_LEVEL = 'ERROR'

相關文章