Splash渲染引擎

Splash渲染引擎

? Splash是Scrapy官方推薦的JavaScript渲染昵慌,它是使用WebKit開發(fā)的輕量級無界面瀏覽器梦抢,提供基于HTTP接口的JavaScript渲染服務(wù),支持以下功能:

  • 為用戶返回經(jīng)過渲染的HTML頁面或頁面截圖氛琢。
  • 并發(fā)渲染多個頁面
  • 關(guān)閉圖片加載,加速渲染
  • 在頁面中執(zhí)行用戶自定義的JavaScript代碼。
  • 執(zhí)行用戶自定義的渲染腳本(lua)白热,功能類似于PhantomJS。

首先安裝Splash粗卜,通過Docker安裝屋确。

$ docker run -p 8050:8050 -p 8051:8051 scrapinghub/splash

或者通過docker-compose.yml

splash:
  container_name: splash
  image: scrapinghub/splash
  restart: always
  ports:
    - "8050:8050"
    - "8051:8051"

詳情可見:http://www.reibang.com/p/1ab7f03f4e5a

安裝完成后,在本機(jī)的8050和8051端口開啟Splash服務(wù)续扔。

? Splash功能豐富乍恐,包含多個服務(wù)端點(diǎn)。這里只介紹兩個最常用的端點(diǎn):

  • render.html:提供JavaScript頁面渲染服務(wù)
  • execute:執(zhí)行用戶自定義的渲染腳本(lua)测砂,利用該端點(diǎn)可在頁面中執(zhí)行JavaScript代碼茵烈。

? Splash文檔地址:http://splash.readthedocs.io/en/latest/api.html

render.html端點(diǎn)

? JavaScript頁面渲染服務(wù)是Splash中最基礎(chǔ)的服務(wù)。

服務(wù)端點(diǎn) render.html
請求地址 http://localhost:8050/render.html
請求方式 GET/POST
返回類型 html

? render.html端點(diǎn)支持的參數(shù)如下表所示砌些。

參數(shù) 是否必選 類型 描述
url 必選 string 需要渲染頁面的url
timeout 可選 float 渲染頁面超時時間
proxy 可選 string 代理服務(wù)器地址
wait 可選 float 等待頁面渲染的時間
images 可選 integer 是否下載圖片呜投,默認(rèn)為1
js_source 可選 string 用戶自定義JavaScript代碼,在頁面渲染前執(zhí)行

? 這里僅列出部分常用參數(shù)存璃,詳細(xì)內(nèi)容參見官方文檔仑荐。

? 下面是使用requests庫調(diào)用render.html端點(diǎn)服務(wù)對頁面:http://quotes.toscrape.com/js/進(jìn)行渲染的示例代碼。

>>> import requests
>>> from scrapy.selector import Selector
>>> splash_url = 'http://localhost:8050/render.html'
>>> args = {'url':'http://quotes.toscrape.com/js', 'timeout':'5', 'image':0}
>>> response  =  requests.get(splash_url, params=args)
>>> sel = Selector(response)
>>> texts = sel.css('div.quote span.text::text').extract()
>>> for text in texts:
...     print text
...
“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”
“It is our choices, Harry, that show what we truly are, far more than our abilities.”
“There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.”
“The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid.”
“Imperfection is beauty, madness is genius and it's better to be absolutely ridiculous than absolutely boring.”
“Try not to become a man of success. Rather become a man of value.”
“It is better to be hated for what you are than to be loved for what you are not.”
“I have not failed. I've just found 10,000 ways that won't work.”
“A woman is like a tea bag; you never know how strong it is until it's in hot water.”
“A day without sunshine is like, you know, night.”

? 在上述代碼中纵东,依據(jù)文檔中的描述設(shè)置參數(shù)url粘招、timeout、images偎球,然后發(fā)送HTTP請求到服務(wù)接口地址洒扎。從運(yùn)行結(jié)果看出,頁面渲染成功衰絮,我們爬取到了頁面中的10條名人名言袍冷。

execute端點(diǎn)

? 在爬取某些頁面時,我們想在頁面中執(zhí)行一些用戶自定義的JavaScript代碼猫牡,例如胡诗,用JavaScript模擬點(diǎn)擊頁面中的按鈕,或調(diào)用頁面中的JavaScript函數(shù)與服務(wù)器交互,利用Splash的execute端點(diǎn)提供的服務(wù)可以實(shí)現(xiàn)這樣的功能煌恢。

服務(wù)端點(diǎn) execute
請求地址 http://localhost:8050/execute
請求方式 POST
返回類型 自定義

execute端點(diǎn)支持的參數(shù)如下表所示骇陈。

參數(shù) 必選/可選 類型 描述
lua_source 必選 string 用戶自定義的lua腳本
timeout 可選 float 渲染頁面超時時間
proxy 可選 string 代理服務(wù)器地址

? 我們可以將execute端點(diǎn)的服務(wù)看做一個可用lua語言編程的瀏覽器,功能類似于PhantomJS瑰抵。使用時需傳遞一個用戶自定義的lua腳本給Splash缩歪,該lua腳本中包含用戶想要模擬的瀏覽器行為,例如:

  • 打開某URL地址的頁面
  • 等待頁面加載及渲染
  • 執(zhí)行JavaScript代碼
  • 獲取HTTP響應(yīng)頭部
  • 獲取Cookie

下面是使用requests庫調(diào)用execute端點(diǎn)服務(wù)的示例代碼:

>>> import requests
>>> import json
>>> lua_script = '''
... function main(splash)
...     splash:go("http://example.com")
...     splash:wait(0.5)
...     local title = splash:evaljs("document.title")
...     return {title=title}
... end
... '''
>>> splash_url = 'http://localhost:8050/execute'
>>> headers = {'content-type':'application/json'}
>>> data = json.dumps({'lua_source':lua_script})
>>> response = requests.post(splash_url, headers=headers, data=data)
>>> response.content
'{"title": "Example Domain"}'
>>> response.json()
{u'title': u'Example Domain'}

? 用戶自定義的lua腳本中必須包含一個main函數(shù)作為程序入口谍憔,main函數(shù)被調(diào)用時會傳入一個splash對象(lua中的對象)匪蝙,用戶可以調(diào)用該對象上的方法操縱Splash。例如习贫,在上面的例子中逛球,先調(diào)用go方法打開某頁面,再調(diào)用wait方法等待頁面渲染苫昌,然后調(diào)用evaljs方法執(zhí)行一個JavaScript表達(dá)式颤绕,并將結(jié)果轉(zhuǎn)換為相應(yīng)的lua對象,最終Splash根據(jù)main函數(shù)的返回值構(gòu)造HTTP響應(yīng)返回給用戶祟身,main函數(shù)的返回值可以是字符串奥务,也可以是lua中的表(類似于Python字典),表會被編碼成json串袜硫。

? 接下來氯葬,看一下splash對象常用的屬性和方法。

  • splash.args屬性:用戶傳入?yún)?shù)的表婉陷,通過該屬性可以訪問用戶傳入的參數(shù)帚称,如splash.args.url、splash.args.wait秽澳。
  • splash.js_enabled屬性:用于開啟/禁止JavaScript渲染闯睹,默認(rèn)為True。
  • splash.images_enabled屬性:用于開啟/禁止圖片加載担神,默認(rèn)為True楼吃。
  • splash:go方法:splash:go{url, baseurl=nil, headers=nil, http_method="GET", body= nil, formdata=nil}類似于在瀏覽器中打開某url地址的頁面,頁面所需資源會被加載妄讯,并進(jìn)行JavaScript渲染孩锡,可以通過參數(shù)指定HTTP請求頭部、請求方法捞挥、表單數(shù)據(jù)等浮创。
  • splash:wait方法:splash:wait{time, cancel_on_redirect=false, cancel_on_error=true}等待頁面渲染,time參數(shù)為等待的秒數(shù)砌函。
  • splash:evajs方法:splash:evajs(snippet)在當(dāng)前頁面下,執(zhí)行一段JavaScript代碼,并返回最后一句表達(dá)式的值讹俊。
  • splash:runjs方法:splash:runjs(snippet)在當(dāng)前頁面下垦沉,執(zhí)行一段JavaScript代碼,與evajs方法相比仍劈,該函數(shù)只執(zhí)行Javasc代碼厕倍,不返回值。
  • splash:url方法:splash:url()獲取當(dāng)前頁面的url贩疙。
  • splash:html方法:splash:html()獲取當(dāng)前頁面的HTML文本讹弯。
  • splash:get_cookies方法:splash:get_cookies()獲取全部Cookie信息

在Scrapy中使用Splash

? 掌握了Splash渲染引擎的基本使用后,我們繼續(xù)學(xué)習(xí)如何在Scrapy中調(diào)用Splash服務(wù)这溅,Python庫的scrape-splash是非常好的選擇组民。

? 使用pip安裝scrape-splash。

$ pip install scrapy-splash

? 在項(xiàng)目環(huán)境中講解scrapy-splash的使用悲靴,創(chuàng)建一個Scrapy項(xiàng)目臭胜,取名為splash_examples:

$ scrapy startproject splash_examples

? 首先在項(xiàng)目配置文件settings.py中對scrappy-splash進(jìn)行配置,添加內(nèi)容如下:

# Splash服務(wù)器地址
SPLASH_URL = 'http://localhost:8050'

# 開啟Splash的兩個下載中間件并調(diào)整HttpCompressionMiddleware的次序
DOWNLOADER_MIDDLEWARES = {
    'scrapy_splash.SplashCookiesMiddleware': 723,
    'scrapy_splash.SplashMiddleware': 725,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
# 設(shè)置去重過濾器
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

# 用來支持cache_args(可選)
SPIDER_MIDDLEWARES = {
    'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}

? 編寫Spider代碼過程中癞尚,使用scrapy_splash調(diào)用Splash服務(wù)非常簡單耸三,scrapy_splash中定義了一個SplashRequest類,用戶只需要使用scrapy_splash.SplashRequest(替代scrapy.Request)提交請求即可浇揩。下面是SplashRequest構(gòu)造器方法中的一些常用參數(shù)仪壮。

  • url:與scrapy.Request中的url相同,也就是待爬取頁面的URL(注意胳徽,不是Splash服務(wù)器地址)
  • headers:與scrapy.Request中的headers相同睛驳。
  • cookies:與scrapy.Request中的cookies相同。
  • args:傳遞給Splash的參數(shù)(除URL以外),如wait膜廊、timeout乏沸、images、js_source等爪瓜。
  • cache_args:如果args中的某些參數(shù)每次調(diào)用都重復(fù)傳遞并且數(shù)據(jù)量較大(例如一段JavaScript代碼)蹬跃,此時可以把該參數(shù)名填入cache_args列表中,讓Splash服務(wù)器緩存該參數(shù)铆铆,如(SplashRequest(url,args={'js_source':js, 'wait':0.5}, cache_args=['js_source']))蝶缀。
  • endpoint:Splash服務(wù)端點(diǎn),默認(rèn)為'render.html',即JavaScript頁面渲染服務(wù)薄货,該參數(shù)可以設(shè)置為'render.json'翁都、'render.har'、'render.png'谅猾、'render.jpeg'柄慰、'execute'等鳍悠,有些服務(wù)端點(diǎn)的功能我們沒有講解,詳細(xì)內(nèi)容可以查閱文檔坐搔。
  • splash_url:Splash服務(wù)器地址藏研,默認(rèn)為None,即使用配置文件中的SPLASH_URL的地址概行。

? 現(xiàn)在蠢挡,大家已經(jīng)對如何在Scrapy中使用Splash渲染引擎爬取動態(tài)頁面有了一定了解,接下來我們在已經(jīng)配置了Splash使用環(huán)境的splash_examples項(xiàng)目中完成兩個實(shí)戰(zhàn)項(xiàng)目凳忙。

項(xiàng)目實(shí)戰(zhàn):爬取toscrape中的名人名言

項(xiàng)目需求

? 爬取網(wǎng)站http://quotes.toscrape.com/js中的名人名言信息业踏。

頁面分析

? 該網(wǎng)站的頁面已在本章開頭部分分析過,大家可以看相關(guān)內(nèi)容涧卵。

編碼實(shí)現(xiàn)

? 首先勤家,在splash_examples項(xiàng)目目錄下使用scrape gensipder命令創(chuàng)建Spider:

$ scrapy genspider quotes quotes.toscrape.com

? 在這個案例中,我們只需使用Splash的render.html端點(diǎn)渲染頁面艺演,再進(jìn)行爬取即可實(shí)現(xiàn)QuotesSpider却紧,代碼如下:

# -*- coding: utf-8 -*-
import scrapy
from scrapy_splash import SplashRequest


class QuotesSpider(scrapy.Spider):
    name = 'quotes'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/js/']

    def start_requests(self):
        for url in self.start_urls:
            yield SplashRequest(url, args={'images': 0, 'timeout': 3})
        pass

    def parse(self, response):
        for sel in response.css('div.quote'):
            quote = sel.css('span.text::text').extract_first()
            author = sel.css('small.author::text').extract_first()
            yield {'quote': quote, 'author': author}
        href = response.css('li.next>a::attr(href)').extract_first()
        if href:
            url = response.urljoin(href)
            yield SplashRequest(url, args={'images': 0, 'timeout': 3})

        pass

? 上述代碼中,使用SplashRequest提交請求胎撤,在SplashRequest的構(gòu)造器中無須傳遞endpoint參數(shù)晓殊,因?yàn)樵搮?shù)默認(rèn)值便是'render.html'。使用args參數(shù)禁止Splash加載圖片伤提,并設(shè)置渲染超時時間巫俺。

? 運(yùn)行爬蟲,觀察結(jié)果:

$ scrapy crawl quotes -o quotes.csv
名人名言

成功爬取了10個頁面中的100條名人名言肿男。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末介汹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子舶沛,更是在濱河造成了極大的恐慌嘹承,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件如庭,死亡現(xiàn)場離奇詭異叹卷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)坪它,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門骤竹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人往毡,你說我怎么就攤上這事蒙揣。” “怎么了开瞭?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵懒震,是天一觀的道長罩息。 經(jīng)常有香客問我,道長挎狸,這世上最難降的妖魔是什么扣汪? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任断楷,我火速辦了婚禮锨匆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冬筒。我一直安慰自己恐锣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布舞痰。 她就那樣靜靜地躺著土榴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪响牛。 梳的紋絲不亂的頭發(fā)上玷禽,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機(jī)與錄音呀打,去河邊找鬼矢赁。 笑死,一個胖子當(dāng)著我的面吹牛贬丛,可吹牛的內(nèi)容都是我干的撩银。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼豺憔,長吁一口氣:“原來是場噩夢啊……” “哼额获!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恭应,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抄邀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后昼榛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體境肾,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年褒纲,在試婚紗的時候發(fā)現(xiàn)自己被綠了准夷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡莺掠,死狀恐怖衫嵌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彻秆,我是刑警寧澤楔绞,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布结闸,位于F島的核電站,受9級特大地震影響酒朵,放射性物質(zhì)發(fā)生泄漏桦锄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一蔫耽、第九天 我趴在偏房一處隱蔽的房頂上張望结耀。 院中可真熱鬧,春花似錦匙铡、人聲如沸图甜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黑毅。三九已至,卻和暖如春钦讳,著一層夾襖步出監(jiān)牢的瞬間矿瘦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工愿卒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缚去,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓掘猿,卻偏偏與公主長得像病游,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子稠通,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理衬衬,服務(wù)發(fā)現(xiàn),斷路器改橘,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 前端開發(fā)者丨h(huán)ttp請求 https:www.rokub.com 前言見解有限滋尉, 如有描述不當(dāng)之處, 請幫忙指出飞主,...
    麋鹿_720a閱讀 10,913評論 11 31
  • 晚上小新洗完澡出來紅著眼睛走到我面前問我:“媽媽碌识,我覺得你這兩天很容易發(fā)火碾篡,你以前是很開心的,而且這兩天你總是干涉...
    米粒2020閱讀 266評論 2 1
  • 最近因?yàn)榻?jīng)濟(jì)和注意力的問題筏餐,個人在得到專欄就訂閱了四個專欄开泽,但是因?yàn)閷诘拈_放集結(jié)了很多有共同成長的人,得到17...
    錢程浩瀚閱讀 169評論 0 0