前段時(shí)間學(xué)習(xí)了用Python寫爬蟲沧烈,使用Scrapy框架爬取京東的商品信息冲泥。商品詳情頁的價(jià)格是由js生成的辅搬,而通過Scrapy直接爬取的源文件中無價(jià)格信息。
通過Selenium环鲤、Phantomjs便能實(shí)現(xiàn)攘轩。下面先介紹Phantomjs狂巢。
(我的博客原文地址:https://chaycao.github.io/2016/08/19/Scrapy-Selenium-Phantomjs/ 請多指教u锍稹)
Phantomjs
作為一個(gè)基于webkit內(nèi)核的沒有UI界面的瀏覽器,大家不必被這個(gè)名字嚇到恋腕,以為是很復(fù)雜的技術(shù)抹锄,其實(shí)只是一個(gè)瀏覽器啦。而其中的一些點(diǎn)擊荠藤、翻頁等操作則由代碼實(shí)現(xiàn)祈远。Phantomjs提供javascript API接口,即我們可以通過js與webkit內(nèi)核交互商源。
只需通過Phantomjs test.js的命令就能成功訪問頁面,并將js生成后的內(nèi)容下載下來谋减。
// a phantomjs example
// test.js
var page = require('webpage').create(); //獲取操作dom或web網(wǎng)頁的對象
var fs = require('fs'); //獲取文件系統(tǒng)對象牡彻,通過它可以操作操作系統(tǒng)的文件操作,包括read出爹、write庄吼、move、copy严就、delete等总寻。
phantom.outputEncoding="utf-8";
//通過page對象打開url鏈接,并可以回調(diào)其聲明的回調(diào)函數(shù)
page.open("http://chaycao.github.io", function(status) {
if ( status === "success" ) {
console.log("成功");
fs.write('web.html',page.content,'w');
} else {
console.log("Page failed to load.");
}
phantom.exit(0);
});
關(guān)于Phantomjs的詳細(xì)介紹可以參照這篇博文:http://blog.csdn.net/tengdazhang770960436/article/details/41320079
Selenium
作為一個(gè)用于Web應(yīng)用程序測試的工具梢为,其測試直接運(yùn)行在瀏覽器中渐行,框架底層使用JavaScript模擬真實(shí)用戶對瀏覽器的操作,從終端用戶的角度測試應(yīng)用程序铸董。將Selenium與Phantomjs聯(lián)系起來祟印,便是我們可以通過使用Selenium操作Phantomjs訪問網(wǎng)頁以獲得js生成后的網(wǎng)頁。
在我看來粟害,這里Selenium的作用就像是Scrapy調(diào)用Phantomjs的中介蕴忆。我也存有疑問:“Scrapy是否能直接調(diào)用Phantomjs?” 期望回復(fù)
Scrapy使用Selenium
需要弄懂一個(gè)概念悲幅,下載中間件套鹅,可以閱讀下官方文檔http://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/downloader-middleware.html
在settings.py加入
DOWNLOADER_MIDDLEWARES = {
'jdSpider.middlewares.middleware.JavaScriptMiddleware': 543, #鍵為中間件類的路徑,值為中間件的順序
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None, #禁止內(nèi)置的中間件
}
第一行為中間件的位置汰具,需要與自己目錄對應(yīng)卓鹿,我的目錄是這樣的:
如果運(yùn)行遇到robots.txt的問題,需要將settings.py中的
ROBOTSTXT_OBEY = False
下面貼上留荔,自定義中間件的代碼:
from selenium import webdriver
from scrapy.http import HtmlResponse
import time
class JavaScriptMiddleware(object):
def process_request(self, request, spider):
if spider.name == "jd":
print "PhantomJS is starting..."
driver = webdriver.PhantomJS() #指定使用的瀏覽器
# driver = webdriver.Firefox()
driver.get(request.url)
time.sleep(1)
js = "var q=document.documentElement.scrollTop=10000"
driver.execute_script(js) #可執(zhí)行js减牺,模仿用戶操作。此處為將頁面拉至最底端。
time.sleep(3)
body = driver.page_source
print ("訪問"+request.url)
return HtmlResponse(driver.current_url, body=body, encoding='utf-8', request=request)
else:
return
在spiders/jd.py中parse()方法接收到的response則是我們自定義中間件返回的結(jié)果拔疚。我們得到的便是js生成后的界面肥隆。
# -*- coding: utf-8 -*-
import scrapy
class JdSpider(scrapy.Spider):
name = "jd"
allowed_domains = ["jd.com"]
start_urls = (
'http://search.jd.com/Search?keyword=三星s7&enc=utf-8&wq=三星s7&pvid=tj0sfuri.v70avo',
)
def parse(self, response):
print response.body