1. 程式人生 > >Python爬蟲scrapy框架爬取動態網站——scrapy與selenium結合爬取資料

Python爬蟲scrapy框架爬取動態網站——scrapy與selenium結合爬取資料

 scrapy框架只能爬取靜態網站。如需爬取動態網站,需要結合著selenium進行js的渲染,才能獲取到動態載入的資料。

如何通過selenium請求url,而不再通過下載器Downloader去請求這個url?

方法:在request物件通過中介軟體的時候,在中介軟體內部開始使用selenium去請求url,並且會得到url對應的原始碼,然後再將   源 程式碼通過response物件返回,直接交給process_response()進行處理,再交給引擎。過程中相當於後續中介軟體的process_request()以及Downloader都跳過了。

相關的配置:

1、scrapy環境中安裝selenium:pip install selenium

2、確保python環境中有phantomJS(無頭瀏覽器)


對於selenium的主要操作是下載中介軟體部分如下圖:

程式碼如下

middlewares.py程式碼:

注意:自定義下載中介軟體,採用selenium的方式!!

# -*- coding: utf-8 -*-

# Define here the models for your spider middleware
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/spider-middleware.html

from scrapy import signals
from selenium import webdriver
from selenium.webdriver import FirefoxOptions
from scrapy.http import HtmlResponse, Response
import time
class TaobaospiderSpiderMiddleware(object): # Not all methods need to be defined. If a method is not defined, # scrapy acts as if the spider middleware does not modify the # passed objects. @classmethod def from_crawler(cls, crawler): # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_spider_input(self, response, spider): # Called for each response that goes through the spider # middleware and into the spider. # Should return None or raise an exception. return None def process_spider_output(self, response, result, spider): # Called with the results returned from the Spider, after # it has processed the response. # Must return an iterable of Request, dict or Item objects. for i in result: yield i def process_spider_exception(self, response, exception, spider): # Called when a spider or process_spider_input() method # (from other spider middleware) raises an exception. # Should return either None or an iterable of Response, dict # or Item objects. pass def process_start_requests(self, start_requests, spider): # Called with the start requests of the spider, and works # similarly to the process_spider_output() method, except # that it doesn’t have a response associated. # Must return only requests (not items). for r in start_requests: yield r def spider_opened(self, spider): spider.logger.info('Spider opened: %s' % spider.name) class TaobaospiderDownloaderMiddleware(object):
# Not all methods need to be defined. If a method is not defined, # scrapy acts as if the downloader middleware does not modify the # passed objects. @classmethod def from_crawler(cls, crawler): # This method is used by Scrapy to create your spiders. s = cls() crawler.signals.connect(s.spider_opened, signal=signals.spider_opened) return s def process_request(self, request, spider): # Called for each request that goes through the downloader # middleware. # Must either: # - return None: continue processing this request # - or return a Response object # - or return a Request object # - or raise IgnoreRequest: process_exception() methods of # installed downloader middleware will be called return None 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 return response def process_exception(self, request, exception, spider): # Called when a download handler or a process_request() # (from other downloader middleware) raises an exception. # Must either: # - return None: continue processing this exception # - return a Response object: stops process_exception() chain # - return a Request object: stops process_exception() chain pass def spider_opened(self, spider): spider.logger.info('Spider opened: %s' % spider.name) *********************下面是相應是自定義的下載中介軟體的替換程式碼************************** class SeleniumTaobaoDownloaderMiddleware(object): # 將driver建立在中介軟體的初始化方法中,適合專案中只有一個爬蟲。 # 爬蟲專案中有多個爬蟲檔案的話,將driver物件的建立放在每一個爬蟲檔案中。 # def __init__(self): # # 在scrapy中建立driver物件,儘可能少的建立該物件。 # # 1. 在初始化方法中建立driver物件; # # 2. 在open_spider中建立deriver物件; # # 3. 不要將driver物件的建立放在process_request(); # option = FirefoxOptions() # option.headless = True # self.driver = webdriver.Firefox(options=option) # 引數spider就是TaobaoSpider()類的物件 def process_request(self, request, spider): if spider.name == "taobao": spider.driver.get(request.url) # 由於淘寶的頁面資料載入需要進行滾動,但並不是所有js動態資料都需要滾動。 for x in range(1, 11, 2): height = float(x) / 10 js = "document.documentElement.scrollTop = document.documentElement.scrollHeight * %f" % height spider.driver.execute_script(js) time.sleep(0.2) origin_code = spider.driver.page_source # 將原始碼構造成為一個Response物件,並返回。 res = HtmlResponse(url=request.url, encoding='utf8', body=origin_code, request=request) # res = Response(url=request.url, body=bytes(origin_code), request=request) return res if spider.name == 'bole': request.cookies = {} request.headers.setDefault('User-Agent','') return None def process_response(self, request, response, spider): print(response.url, response.status) return response

taobao.py 程式碼如下:

# -*- coding: utf-8 -*-
import scrapy
from selenium import webdriver
from selenium.webdriver import FirefoxOptions


class TaobaoSpider(scrapy.Spider):
    """
    scrapy框架只能爬取靜態網站。如需爬取動態網站,需要結合著selenium進行js的渲染,才能獲取到動態載入的資料。

    如何通過selenium請求url,而不再通過下載器Downloader去請求這個url?
    方法:在request物件通過中介軟體的時候,在中介軟體內部開始使用selenium去請求url,並且會得到url對應的原始碼,然後再將原始碼通過response物件返回,直接交給process_response()進行處理,再交給引擎。過程中相當於後續中介軟體的process_request()以及Downloader都跳過了。

    """
    name = 'taobao'
    allowed_domains = ['taobao.com']
    start_urls = ['https://s.taobao.com/search?q=%E7%AC%94%E8%AE%B0%E6%9C%AC%E7%94%B5%E8%84%91&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306']
    
    def __init__(self):
        # 在初始化淘寶物件時,建立driver
        super(TaobaoSpider, self).__init__(name='taobao')
        option = FirefoxOptions()
        option.headless = True
        self.driver = webdriver.Firefox(options=option)

    def parse(self, response):
        """
        提取列表頁的商品標題和價格
        :param response:
        :return:
        """
        info_divs = response.xpath('//div[@class="info-cont"]')
        print(len(info_divs))
        for div in info_divs:
            title = div.xpath('.//a[@class="product-title"]/@title').extract_first('')
            price = div.xpath('.//span[contains(@class, "g_price")]/strong/text()').extract_first('')
            print(title, price)

settings.py程式碼如下圖:


關於程式碼中提到的初始化driver的位置有以下兩種情況:

1、只存在一個爬蟲檔案的話,driver初始化函式可以定義在middlewares.py的自定義中介軟體中(如上述程式碼註釋初始化部分)也可以在爬蟲檔案中自定義(如上述程式碼在爬蟲檔案中初始化)。

注意:如果只有一個爬蟲檔案就不需要在自定義的process_requsests中判斷是哪一個爬蟲專案然後分別請求!

2、如果存在兩個或兩個以上爬蟲專案(如下圖專案結構)的時候,需要將driver的初始化函式定義在各自的爬蟲專案檔案下(如上述程式碼),同時需要在process_requsests判斷是那個爬蟲專案的請求!!

          

相關推薦

Python爬蟲scrapy框架動態網站——scrapyselenium結合資料

 scrapy框架只能爬取靜態網站。如需爬取動態網站,需要結合著selenium進行js的渲染,才能獲取到動態載入的資料。如何通過selenium請求url,而不再通過下載器Downloader去請求這個url?方法:在request物件通過中介軟體的時候,在中介軟體內部開始

scrapy爬蟲動態網站

爬取360圖片上的美女圖片 360圖片網站上的圖片是動態載入的,動態載入 就是通過ajax請求介面拿到資料喧染在網頁上。我們就可以通過遊覽器的開發者工具分析,在我們向下拉動視窗時就會出現這麼個請求,如圖所示: 所以就判定這個url就是ajax請求的介面:

Python爬蟲: "追新番"網站資源鏈接

== n) web ace class timeout grep target true “追新番”網站 追新番網站提供最新的日劇和日影下載地址,更新比較快。 個人比較喜歡看日劇,因此想著通過爬取該網站,做一個資源地圖 可以查看網站到底有哪些日劇,並且隨時可以下載。 資源地

python:爬蟲之Post請求以及動態Ajax資料(3)

#爬蟲的post方式 作用:對引數進行打包反饋給伺服器 import urllib.request import urllib.parse #對引數打包 url = "http://www.sunck.wang:8085/form" data = { "use

python爬蟲知識點總結(九)Requests+正則表達式貓眼電影

bsp code item 代碼 proc action none width auth 一、爬取流程 二、代碼演示 #-*- coding: UTF-8 -*- #_author:AlexCthon #mail:[email protected] #date:20

Python爬蟲入門教程 4-100 美空網未登入圖片

簡介 上一篇寫的時間有點長了,接下來繼續把美空網的爬蟲寫完,這套教程中編寫的爬蟲在實際的工作中可能並不能給你增加多少有價值的技術點,因為它只是一套入門的教程,老鳥你自動繞過就可以了,或者帶帶我也行。 爬蟲分析 首先,我們已經爬取到了N多的使用者個人主頁,我通過連結拼接獲取到了 www.moko.cc/

Python爬蟲入門教程 10-100 圖蟲網多執行緒

寫在前面 經歷了一頓噼裡啪啦的操作之後,終於我把部落格寫到了第10篇,後面,慢慢的會涉及到更多的爬蟲模組,有人問scrapy 啥時候開始用,這個我預計要在30篇以後了吧,後面的套路依舊慢節奏的,所以莫著急了,100篇呢,預計4~5個月寫完,常見的反反爬後面也會寫的,還有fuck login類的內容。

Python爬蟲入門教程 10-100 圖蟲網多線程

全局變量 app str tlist img exception 父類 json urn 寫在前面 經歷了一頓劈裏啪啦的操作之後,終於我把博客寫到了第10篇,後面,慢慢的會涉及到更多的爬蟲模塊,有人問scrapy 啥時候開始用,這個我預計要在30篇以後了吧,後面的套路依舊慢

動態網站資料(soup的css方式處理資料

import requests from bs4 import BeautifulSoup url = 'https://knewone.com/discover?page=' def get_in

Python爬蟲入門教程 14-100 All IT eBooks多執行緒

寫在前面 對一個爬蟲愛好者來說,或多或少都有這麼一點點的收集癖 ~ 發現好的圖片,發現好的書籍,發現各種能存放在電腦上的東西,都喜歡把它批量的爬取下來。 然後放著,是的,就這麼放著.......然後慢慢的遺忘掉..... 爬蟲分析 開啟網址 http://www.allitebooks.c

Python爬蟲入門教程 10-100 圖蟲網多執行緒

寫在前面 經歷了一頓噼裡啪啦的操作之後,終於我把部落格寫到了第10篇,後面,慢慢的會涉及到更多的爬蟲模組,有人問 scrapy 啥時候開始用,這個我預計要在30篇以後了吧,後面的套路依舊慢節奏的,所以莫著急了,100篇呢,預計4~5個月寫完,常見的反反爬後面也會寫的,還有fuck login類的

Scrapy筆記(12)- 抓動態網站

前面我們介紹的都是去抓取靜態的網站頁面,也就是說我們開啟某個連結,它的內容全部呈現出來。但是如今的網際網路大部分的web頁面都是動態的,經常逛的網站例如京東、淘寶等,商品列表都是js,並有Ajax渲染,下載某個連結得到的頁面裡面含有非同步載入的內容,這樣再使用之前的方式我們根本獲取不到非同步載入的這些網頁內

Python爬蟲實例(四)網站模擬登陸

opener 運行 webkit zh-cn head window targe Coding 破解 一、獲取一個有登錄信息的Cookie模擬登陸 下面以人人網為例,首先使用自己的賬號和密碼在瀏覽器登錄,然後通過抓包拿到cookie,再將cookie放到請求之中發送請求即可

Scrapy分布式爬蟲之ES搜索引擎網站|Scrapy爬蟲視頻教程

視頻 網絡爬蟲 管理系 搜索引擎 聚類 醫療 esql pan 網絡知識 Scrapy分布式爬蟲之ES搜索引擎網站 分享網盤地址——https://pan.baidu.com/s/1smNcos1 密碼:wnze 備用地址(騰訊微雲):http://url.cn/51n4s

爬蟲Scrapy框架-Crawlspider鏈接提取器規則解析器

一個 htm turn 創建 for tin Coding lines spi 一:Crawlspider簡介     CrawlSpider其實是Spider的一個子類,除了繼承到Spider的特性和功能外,還派生除了其自己獨有的更加強大的特性和功能。其中最顯著的功能就是

記錄一次python爬蟲批量下載一個校花網站的妹子圖片

學python也快2個禮拜了,從開始看別人寫的爬蟲程式碼,然後試著抄著學習,感覺沒太大進步,最大收穫就是改了幾處bug(可能有些地方不適用我的pyyhon平臺報錯)。 中午看到一個帖子校花妹子圖使用爬蟲進行批量下載,看了下,感覺不錯(我說的技術,哈哈哈)。 然後決定自己寫一個爬蟲,已經看書兩個禮

python爬蟲使用框架

scrapy pip install scrapy beautifulsoup pip install beautifulsoup4 selenium pip install selenium 滑動驗證碼 S

python爬蟲(五):實戰 【5. 使用正則亞馬遜價格】

使用正則定位價格,更簡單 import requests import re url = 'https://www.amazon.cn/s/field-keywords=spark' # 隱藏爬蟲 head = {'user-agent':'Mozilla/5.0 (Window

使用scrapyselenium結合 淘寶資訊

首先,發現淘寶資訊是需要進行下拉載入資訊,否則商品資訊為空 因此,在middleware.py中設定: class ScrapyseleniumspiderDownloaderMiddleware(object): # def __init__(self):

Python丨如果是動態網站可以採用selenium的三種等待方式進行解讀

  如果網站採用了動態html技術,那麼頁面上的部分元素出現時間便不能確定,這個時候就可以設定一個等待時間,強制要求在時間內出現,否則報錯,那麼我可以用等待。 說到等待,又有三種等法,且聽小編 一 一道來: Python學習資料或者需要程式碼、視訊加Python學習群:9