javascript
js动态渲染html页面,利用Scrapy-Splash抓取JS动态渲染的网页数据
隨著越來越多的網(wǎng)站開始用JS在客戶端瀏覽器動態(tài)渲染網(wǎng)站,導致很多我們需要的數(shù)據(jù)并不能由原始的html中獲取,再加上Scrapy本身并不提供JS渲染解析的功能,通常對這類網(wǎng)站數(shù)據(jù)的爬取我們一般采用兩種方法:
通過分析網(wǎng)站,找到對應數(shù)據(jù)的接口,模擬接口去獲取我們需要的數(shù)據(jù)(參見Scrapy抓取Ajax動態(tài)頁面),但是一旦該網(wǎng)站的接口隱藏的很深,或者接口的加密過于復雜,此種方法可能就有點行不通了
借助JS內(nèi)核,將獲取到的含有JS腳本的頁面交由JS內(nèi)核去渲染,最后將渲染后生成的html返回給Scrapy分析,比較常見的WebKit和Scrapy-Splash
本篇文章的目的就是用來介紹如何使用Scrapy-Splash來配合Scrapy抓取動態(tài)頁面這個問題。
準備工作
Docker安裝,具體安裝步驟參考Docker官網(wǎng)
為什么要安裝Docker?
因為Scrapy-Splash使用了Splash HTTP API,所以你需要提供一個Splash實例,而在Docker鏡像中已經(jīng)有現(xiàn)成的Splash實例了,可以很方便的使用。
安裝運行Splash
docker pull scrapinghub/splash #從docker鏡像中拉取splash實例
docker run -p 8050:8050 scrapinghub/splash #啟動splash實例
Scrapy配置
在Scrapy項目的setting.py中加入如下內(nèi)容:
SPLASH_URL = 'http://localhost:8050'
DOWNLOADER_MIDDLEWARES = {
'scrapy_splash.SplashCookiesMiddleware': 723,
'scrapy_splash.SplashMiddleware': 725,
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
SPIDER_MIDDLEWARES = {
'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
實際代碼解析
我們以騰訊證券這個頁面為例,騰訊的證券新聞列表是js動態(tài)渲染而成
我們直接打開這個鏈接,然后打開開發(fā)者工具,定位到新聞列表處:
我們在從network中查看第一次請求的Response時發(fā)現(xiàn),返回的html中該列表頁處是空的
實際的數(shù)據(jù)被藏著JS里,加載完成后由JS操作DOM插入完成
此處由于實際數(shù)據(jù)被塞到了一段JS的變量里面,并不是由Ajax調用接口獲取的,因此為了避免自己手動去截取js變量,我們便將該頁面交給Scrapy-Splash渲染
import scrapy
from FinancialInfoSpider.items import ArticleItem
from scrapy_splash import SplashRequest
from w3lib.html import remove_tags
import re
from bs4 import BeautifulSoup
class TencentStockSpider(scrapy.Spider):
name = "TencentStock"
def start_requests(self):
urls = [
'http://stock.qq.com/l/stock/ywq/list20150423143546.htm',
]
for url in urls:
yield SplashRequest(url, self.parse, args={'wait': 0.5})
def parse(self,response):
sel = scrapy.Selector(response)
links = sel.xpath("//div[@class='qq_main']//ul[@class='listInfo']//li//div[@class='info']//h3//a/@href").extract()
requests = []
for link in links:
request = scrapy.Request(link, callback =self.parse_article)
requests.append(request)
return requests
def parse_article(self,response):
sel = scrapy.Selector(response)
article = ArticleItem()
article['title'] = sel.xpath('//*[@id="Main-Article-QQ"]/div/div[1]/div[1]/div[1]/h1/text()').extract()[0]
article['source'] = sel.xpath('//*[@id="Main-Article-QQ"]/div/div[1]/div[1]/div[1]/div/div[1]/span[2]').xpath('string(.)').extract()[0]
article['pub_time'] = sel.xpath('//*[@id="Main-Article-QQ"]/div/div[1]/div[1]/div[1]/div/div[1]/span[3]/text()').extract()[0]
html_content = sel.xpath('//*[@id="Cnt-Main-Article-QQ"]').extract()[0]
article['content'] = self.remove_html_tags(html_content)
return article
def remove_html_tags(self,html):
soup = BeautifulSoup(html)
[s.extract() for s in soup('script')]
[s.extract() for s in soup('style')]
content = ''
for substring in soup.stripped_strings:
content = content + substring
return content
主要代碼就一句,將獲取到的頁面發(fā)送給本地的Splash實例去渲染解析,最后將結果返回給parse函數(shù)解析
SplashRequest(url, self.parse, args={'wait': 0.5})
里面用了BeautifulSoup這個庫去除了html中得script和style標簽,具體用法可以參考這兩篇文章:
輸出結果:
總結
以上是生活随笔為你收集整理的js动态渲染html页面,利用Scrapy-Splash抓取JS动态渲染的网页数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 永安行发布全球首台微型太阳能制充氢一体机
- 下一篇: 2021信阳高中高考成绩查询,河南省普通