問題
有的頁面的很多部分都是用JS生成的,而對於用scrapy爬蟲來說就是一個很大的問題,因為scrapy沒有JS engine,所以爬取的都是靜態頁面,對於JS生成的動態頁面都無法獲得
官網http://splash.readthedocs.io/en/stable/
解決方案
- 利用第三方中間件來提供JS渲染服務: scrapy-splash 等
- 利用webkit或者基於webkit庫
Splash是一個Javascript渲染服務。它是一個實現了HTTP API的輕量級瀏覽器,Splash是用Python實現的,同時使用Twisted和QT。Twisted(QT)用來讓服務具有異步處理能力,以發揮webkit的並發能力
安裝
- pip安裝scrapy-splash庫
pip install scrapy-splash
- scrapy-splash使用的是Splash HTTP API, 所以需要一個splash instance,一般采用docker運行splash,所以需要安裝docker
- 安裝docker, 安裝好后運行docker
- 拉取鏡像
docker pull scrapinghub/splash
- 用docker運行scrapinghub/splash
docker run -p 8050:8050 scrapinghub/splash
-
配置splash服務(以下操作全部在settings.py):
- 使用splash解析,要在配置文件中設置splash服務器地址:
SPLASH_URL = 'http://192.168.99.100:8050/'
- 將splash middleware添加到DOWNLOADER_MIDDLEWARE中
DOWNLOADER_MIDDLEWARES = { 'scrapy_splash.SplashCookiesMiddleware': 723, 'scrapy_splash.SplashMiddleware': 725, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, }
- Enable SplashDeduplicateArgsMiddleware
SPIDER_MIDDLEWARES = { 'scrapy_splash.SplashDeduplicateArgsMiddleware': 100 }
這個中間件需要支持cache_args功能; 它允許通過不在磁盤請求隊列中多次存儲重復的Splash參數來節省磁盤空間。如果使用Splash 2.1+,則中間件也可以通過不將這些重復的參數多次發送到Splash服務器來節省網絡流量
- 配置消息隊列所使用的過濾類
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
- 配置消息隊列需要使用的類
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
樣例
import scrapy
from scrapy_splash import SplashRequest
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['douban.com']
def start_requests(self):
yield SplashRequest('https://movie.douban.com/typerank?type_name=劇情&type=11&interval_id=100:90', args={'wait': 0.5})
def parse(self, response):
print(response.text)