小白學 Python 爬蟲(41):爬蟲框架 Scrapy 入門基礎(八)對接 Splash 實戰
人生苦短,我用 Python
前文傳送門:
小白學 Python 爬蟲(1):開篇
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門
小白學 Python 爬蟲(5):前置準備(四)資料庫基礎
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝
小白學 Python 爬蟲(7):HTTP 基礎
小白學 Python 爬蟲(8):網頁基礎
小白學 Python 爬蟲(9):爬蟲基礎
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
小白學 Python 爬蟲(12):urllib 基礎使用(二)
小白學 Python 爬蟲(13):urllib 基礎使用(三)
小白學 Python 爬蟲(14):urllib 基礎使用(四)
小白學 Python 爬蟲(15):urllib 基礎使用(五)
小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖
小白學 Python 爬蟲(17):Requests 基礎使用
小白學 Python 爬蟲(18):Requests 進階操作
小白學 Python 爬蟲(19):Xpath 基操
小白學 Python 爬蟲(20):Xpath 進階
小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)
小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)
小白學 Python 爬蟲(23):解析庫 pyquery 入門
小白學 Python 爬蟲(24):2019 豆瓣電影排行
小白學 Python 爬蟲(25):爬取股票資訊
小白學 Python 爬蟲(26):為啥買不起上海二手房你都買不起
小白學 Python 爬蟲(27):自動化測試框架 Selenium 從入門到放棄(上)
小白學 Python 爬蟲(28):自動化測試框架 Selenium 從入門到放棄(下)
小白學 Python 爬蟲(29):Selenium 獲取某大型電商網站商品資訊
小白學 Python 爬蟲(30):代理基礎
小白學 Python 爬蟲(31):自己構建一個簡單的代理池
小白學 Python 爬蟲(32):非同步請求庫 AIOHTTP 基礎入門
小白學 Python 爬蟲(33):爬蟲框架 Scrapy 入門基礎(一)
小白學 Python 爬蟲(34):爬蟲框架 Scrapy 入門基礎(二)
小白學 Python 爬蟲(35):爬蟲框架 Scrapy 入門基礎(三) Selector 選擇器
小白學 Python 爬蟲(36):爬蟲框架 Scrapy 入門基礎(四) Downloader Middleware
小白學 Python 爬蟲(37):爬蟲框架 Scrapy 入門基礎(五) Spider Middleware
小白學 Python 爬蟲(38):爬蟲框架 Scrapy 入門基礎(六) Item Pipeline
小白學 Python 爬蟲(39): JavaScript 渲染服務 Scrapy-Splash 入門
小白學 Python 爬蟲(40):爬蟲框架 Scrapy 入門基礎(七)對接 Selenium 實戰
引言
前面我們介紹了使用 Scrapy 對接 Selenium 來抓取由 JavaScript 動態渲染的網頁,那麼除了這種方式,是否還有其他的解決方案?
答案當然是肯定的,前面我們同樣介紹了 Splash 這個 JavaScript 動態渲染服務,本篇文章,我們就來介紹如何使用 Scrapy 對接 Splash 抓取由 JavaScript 動態渲染的網頁。
示例
準備
首先需確保已經正確安裝 Splash 服務,同時包括 Scrapy-Splash 庫,還沒有安裝的同學,可以參考前面的文章 「小白學 Python 爬蟲(39): JavaScript 渲染服務 Scrapy-Splash 入門」 進行安裝。
新建專案
本篇內容還是新建一個新的 Scrapy 專案,並且命名為 scrapy_splash_demo ,命令如下:
scrapy startproject scrapy_splash_demo
記得找一個自己喜歡的目錄,最好是純英文目錄。
然後新建一個 Spider ,命令如下:
scrapy genspider jd www.jd.com
本篇的示例嘛還是使用之前 Splash 的示例,畢竟本文的內容主要是介紹 Scrapy 如何對接 Splash ,當然另一個更主要的原因是小編也比較懶嘛~~~
配置
這裡的配置可以參考官方的 Github 倉庫,連結:https://github.com/scrapy-plugins/scrapy-splash 。
首先先在 settings.py
中新增 Splash 服務的地址,因為小編這裡使用的是本地的服務,所以直接就配置了本地的連結。
SPLASH_URL = 'http://localhost:8050/'
如果 Splash 服務是在遠端的伺服器上執行的,那麼這裡就應該配置遠端伺服器的地址,如 Splash 服務是執行在遠端的 172.16.15.177 上的,那麼需要的配置就是:
SPLASH_URL = 'http://172.16.15.177:8050/'
接下里需要配置幾個 DOWNLOADER_MIDDLEWARES
,如下:
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
我們還需要配置一個 SPIDER_MIDDLEWARES
,如下:
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
接下來,需要配置一個去重的 Python 類 SplashAwareDupeFilter
,如下:
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
我們還需要配置一個 Cache 儲存的 SplashAwareFSCacheStorage
,如下:
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
接下來,我們就可以開始搞事情了。
傳送請求
上面我們已經將該配置的都配置完成了,這裡我們可以直接使用 SplashRequest 物件並傳遞相應的引數, Scrapy 會將此請求轉發給 Splash ,Splash 將頁面載入渲染,渲染完成後再將結果傳遞回來,這時的 Response 就是經過 Splash 渲染的結果了,這裡直接交給 Spider 解析就好了。
我們先來看下官方的示例,如下:
yield SplashRequest(url, self.parse_result,
args={
# optional; parameters passed to Splash HTTP API
'wait': 0.5,
# 'url' is prefilled from request url
# 'http_method' is set to 'POST' for POST requests
# 'body' is set to request body for POST requests
},
endpoint='render.json', # optional; default is render.html
splash_url='<url>', # optional; overrides SPLASH_URL
slot_policy=scrapy_splash.SlotPolicy.PER_DOMAIN, # optional
)
這裡直接構造了一個 SplashRequest 物件,前兩個引數是目標 URL 以及回撥的方法,另外我們可以通過 args 傳遞一些引數,如等待的時間,這個示例中是 0.5 。
更多的說明還是參考官方 Github 倉庫,地址:https://github.com/scrapy-plugins/scrapy-splash 。
或者我們也可以使用 scrapy.Request , Splash 相關的配置通過 meta 配置就好了,接著看一個官方的示例,如下:
yield scrapy.Request(url, self.parse_result, meta={
'splash': {
'args': {
# set rendering arguments here
'html': 1,
'png': 1,
# 'url' is prefilled from request url
# 'http_method' is set to 'POST' for POST requests
# 'body' is set to request body for POST requests
},
# optional parameters
'endpoint': 'render.json', # optional; default is render.json
'splash_url': '<url>', # optional; overrides SPLASH_URL
'slot_policy': scrapy_splash.SlotPolicy.PER_DOMAIN,
'splash_headers': {}, # optional; a dict with headers sent to Splash
'dont_process_response': True, # optional, default is False
'dont_send_headers': True, # optional, default is False
'magic_response': False, # optional, default is True
}
})
這兩種傳送 Request 請求的方式是相同的,選哪個都可以。
本篇文章中使用的 Lua 指令碼還是之前文章中的指令碼,具體 Lua 指令碼內容如下:
function main(splash, args)
splash:go("https://www.jd.com/")
return {
url = splash:url(),
jpeg = splash:jpeg(),
har = splash:har(),
cookies = splash:get_cookies()
}
end
結果如下:
接下來,我們在 Spider 中使用 SplashRequest 對接 Lua 指令碼就好了,事情就是這麼簡單,如下:
# -*- coding: utf-8 -*-
import scrapy
from scrapy_splash import SplashRequest
lua_script = """
function main(splash, args)
splash:go(args.url)
return {
url = splash:url(),
jpeg = splash:jpeg(),
har = splash:har(),
cookies = splash:get_cookies()
}
end
"""
class JdSpider(scrapy.Spider):
name = 'jd'
allowed_domains = ['www.jd.com']
start_urls = ['http://www.jd.com/']
def start_requests(self):
url = 'https://www.jd.com/'
yield SplashRequest(url=url, callback=self.parse)
def parse(self, response):
self.logger.debug(response.text)
Spider 寫好了以後可以使用命令執行這個爬蟲了,命令如下:
scrapy crawl jd
具體的結果小編這裡就不貼了,只是簡單的將響應回來的資料已日誌的形式打印出來了,不過如果仔細觀察打出來的資料,可以看到原來由 JavaScript 動態渲染的部分也打印出來了,說明我們的 Scrapy 對接 Splash 實戰成功。
示例程式碼
本系列的所有程式碼小編都會放在程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。
示例程式碼-Github
示例程式碼-Gi