在之前的章節(jié)中屁擅,爬取的都是靜態(tài)頁(yè)面中的信息序宦,隨著越來(lái)越多的網(wǎng)站開(kāi)始用JS在客戶端瀏覽器動(dòng)態(tài)渲染網(wǎng)站滥玷,導(dǎo)致很多需要的數(shù)據(jù)并不能在原始的HTML中獲取辟癌,再加上Scrapy本身并不提供JS渲染解析的功能寒屯,那么如何通過(guò)Scrapy爬取動(dòng)態(tài)網(wǎng)站的數(shù)據(jù)呢?這一章節(jié)我們將學(xué)習(xí)這些知識(shí)黍少。
通常對(duì)這類網(wǎng)站數(shù)據(jù)的爬取采用如下兩種方法:
- 通過(guò)分析網(wǎng)站寡夹,找到對(duì)應(yīng)數(shù)據(jù)的接口,模擬接口去獲取需要的數(shù)據(jù)(一般也推薦這種方式厂置,畢竟這種方式的效率最高)菩掏,但是很多網(wǎng)站的接口隱藏的很深,或者接口的加密非常復(fù)雜昵济,導(dǎo)致無(wú)法獲取到它們的數(shù)據(jù)接口智绸,此種方法很可能就行不通。
- 借助JS內(nèi)核访忿,將獲取到的含有JS腳本的頁(yè)面交由JS內(nèi)核去渲染瞧栗,最后將渲染后生成的HTML返回給Scrapy解析,Splash是Scrapy官方推薦的JS渲染引擎醉顽,它是使用Webkit開(kāi)發(fā)的輕量級(jí)無(wú)界面瀏覽器沼溜,提供基于HTML接口的JS渲染服務(wù)。
一游添、搭建Splash服務(wù)
如何在Scrapy中調(diào)用Splash服務(wù)系草?Python庫(kù)的scrapy-splash是一個(gè)非常好的選擇,下面就來(lái)講解如何使用scrapy-splash唆涝。
- 利用pip安裝scrapy-splash庫(kù):
$ pip install scrapy-splash
- scrapy-splash使用的是Splash HTTP API找都,所以需要一個(gè)splash instance,一般采用docker運(yùn)行splash廊酣,所以需要安裝docker:
$ sudo apt-get install docker
如果是Mac的話需要使用brew安裝能耻,如下:
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
$ brew install docker
- 拉取鏡像:
$ sudo docker pull scrapinghub/splash
如果出現(xiàn)如下錯(cuò)誤時(shí),說(shuō)明已確定Docker本身已經(jīng)安裝正常。
Using default tag: latest
Warning: failed to get default registry endpoint from daemon (Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?). Using system default: https://index.docker.io/v1/
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
問(wèn)題原因是因?yàn)閐ocker服務(wù)沒(méi)有啟動(dòng)晓猛,在相應(yīng)的/var/run/ 路徑下找不到docker的進(jìn)程饿幅。
執(zhí)行service docker start
命令,啟動(dòng)docker服務(wù)戒职。
- 使用docker開(kāi)啟Splash服務(wù):
$ sudo docker run -p 8050:8050 scrapinghub/splash
- 在項(xiàng)目配置文件settings.py中配置splash服務(wù):
1)添加splash服務(wù)器地址:
SPLASH_URL = 'http://localhost:8050'
2)將splash middleware添加到DOWNLOADER_MIDDLEWARE中:
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
3)支持cache_args(可選):
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
4)設(shè)置去重過(guò)濾器:
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
二栗恩、使用Splash服務(wù)
Splash功能豐富,包含多個(gè)服務(wù)端點(diǎn)洪燥,最常用的有兩個(gè)端點(diǎn):
- render.html
提供JS頁(yè)面渲染服務(wù)磕秤。 - execute
執(zhí)行用戶自定義的渲染腳本,利用該端點(diǎn)可在頁(yè)面中執(zhí)行JS代碼捧韵。
舉一個(gè)簡(jiǎn)單的例子市咆,使用scrapy_splash.SplashRequest渲染JS請(qǐng)求,如下:
import scrapy
from scrapy_splash import SplashRequest
class MySpider(scrapy.Spider):
# 假設(shè)這個(gè)請(qǐng)求的頁(yè)面數(shù)據(jù)是需要執(zhí)行JS才能爬取的
start_urls = ["http://example.com"]
def start_requests(self):
for url in self.start_urls:
yield SplashRequest(url, self.parse, args={'images':0,'timeout': 5})
def parse(self, response):
# ...
上述代碼中再来,用戶只需使用scrapy_splash.SplashRequest替代scrapy.Request提交請(qǐng)求即可完成JS渲染蒙兰,并且在SplashRequest的構(gòu)造器中無(wú)須傳遞endpoint參數(shù),因?yàn)樵搮?shù)默認(rèn)值就是‘render.html’其弊。
下面介紹下SplashRequest構(gòu)造器方法中的一些常用參數(shù)癞己。
- url
與scrapy.Request中的url相同膀斋,也就是待爬取頁(yè)面的url梭伐。 - headers
與scrapy.Request中的headers相同。 - cookies
與scrapy.Request中的cookies相同仰担。 - args
傳遞給Splash的參數(shù)糊识,如wait(等待時(shí)間)、timeout(超時(shí)時(shí)間)摔蓝、images(是否禁止加載圖片赂苗,0禁止,1不禁止)等贮尉。 - endpoint
Splash服務(wù)端點(diǎn)拌滋,默認(rèn)為‘render.html’,即JS頁(yè)面渲染服務(wù)猜谚。 - splash_url
Splash服務(wù)器地址败砂,默認(rèn)為None,即使用settings.py配置文件中的SPLASH_URL = 'http://localhost:8050'
三魏铅、項(xiàng)目實(shí)戰(zhàn)
放在下一章節(jié)講解