https://www.bbsmax.com/A/kvJ362GQzg/
經過一下午的折騰,找到了一篇寫的好的文章,講的是處理JS渲染的HTML界面,原文鏈接如上。
webMagic雖然方便,但是也有它不適用的地方,比如定向的某個單頁面爬蟲,或者存在大量ajax請求,頁面的跳轉請求全都混淆在js裏。
這時可以用webMagic結合phantomjs來真實模擬頁面請求,即不僅僅獲取數據,而是將整個頁面完整渲染出來。雖然這樣會使爬蟲速度變慢很多,但是不失爲一種快捷方便的解決方法。
PhantomJS是一個基於 WebKit 的服務器端JavaScript API。它全面支持web而不需瀏覽器支持,其快速,原生支持各種Web標準: DOM 處理, CSS 選擇器, JSON, Canvas, 和 SVG。 PhantomJS 可以用於頁面自動化 , 網絡監測, 網頁截屏,以及 無界面測試 等。
淘寶就是這種難以用普通爬蟲方法爬取的網站。直接發送GET請求到淘寶基本獲取不到什麼有效的內容和鏈接。
還好webMagic雖然默認使用httpClient獲取網頁,但是它也將它獲取網頁的方法Downloader開放出來。這樣可以在Downloader裏使用phantomjs獲取頁面。
phantomjs使用方法
1.下載安裝phantomjs
2.編寫js腳本
system = require('system') //傳遞一些需要的參數給js文件
address = system.args[1];//獲得命令行第二個參數 ,也就是指定要加載的頁面地址,接下來會用到
var page = require('webpage').create();
var url = address;
page.open(url, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
var encodings = ["euc-jp", "sjis", "utf8", "System"];//這一步是用來測試輸出的編碼格式,選擇合適的編碼格式很重要,不然你抓取下來的頁面會亂碼o(╯□╰)o,給出的幾個編碼格式是官網上的例子,根據具體需要自己去調整。
for (var i = 3; i < encodings.length; i++) {//我這裏只要一種編碼就OK啦
phantom.outputEncoding = encodings[i];
console.log(phantom.outputEncoding+page.content);//最後返回webkit加載之後的頁面內容
}
}
phantom.exit();
});
3.測試
package util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.selector.PlainText;
public class GetAjaxHtml {
public static String getAjaxContent(String url) throws Exception {
Runtime rt = Runtime.getRuntime();
Process p = rt
.exec("D:/phantomjs-2.1.1-windows/bin/phantomjs.exe D:/s.js "
+ url);
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sbf = new StringBuffer();
String tmp = "";
while ((tmp = br.readLine()) != null) {
sbf.append(tmp + "\n");
}
return sbf.toString();
}
public static Page download(Request request) {
Page page = new Page();
try {
String url = request.getUrl();
String html = getAjaxContent(url);
page.setRawText(html);
page.setUrl(new PlainText(url));
page.setRequest(request);
return page;
} catch (Exception e) {
System.out.println("download出錯了!");
return page;
}
}
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
String result = getAjaxContent("http://www.taobao.com");
System.out.println(result);
// 創建新文件
String path = "D:\\testFile\\taobao.html";
PrintWriter printWriter = null;
printWriter = new PrintWriter(new FileWriter(new File(path)));
printWriter.write(result);
printWriter.close();
long end = System.currentTimeMillis();
System.out.println("===============耗時:" + (end - start)
+ "===============");
}
}
webMagic結合phantomjs淘寶爬蟲
package taobao;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.downloader.Downloader;
import us.codecraft.webmagic.processor.PageProcessor;
import util.GetAjaxHtml;
import util.UuidUtil;
import csdnblog.dao.TaobaoDao;
import csdnblog.model.Taobao;
public class TaobaoPageProcessor implements PageProcessor {
private TaobaoDao taobaoDao = new TaobaoDao();
// 抓取網站的相關配置,包括:編碼、抓取間隔、重試次數等
private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
@Override
public Site getSite() {
return site;
}
@Override
public void process(Page page) {
page.addTargetRequests(page.getHtml().links()
.regex(".*item\\.taobao\\.com/item\\.htm\\?id=.*")
.all());
page.addTargetRequests(page.getHtml().links()
.regex("https://s\\.taobao\\.com/list.*")
.all());
//如果是詳情頁
if(page.getUrl().regex("https://item\\.taobao\\.com/item\\.htm\\?id=.*").match()) {
Taobao taobao = new Taobao();
taobao.setId(UuidUtil.getId());
taobao.setUrl(page.getUrl().toString());
taobao.setMaintitle(page.getHtml().xpath("//h3[@class='tb-main-title']/text()").get());
taobao.setSubtitle(page.getHtml().xpath("//p[@class='tb-subtitle']/text()").get());
taobao.setPrice(page.getHtml().xpath("//strong[@id='J_StrPrice']/em[@class='tb-rmb-num']/text()").get());
taobao.setTaobaoprice(page.getHtml().xpath("//em[@id='J_PromoPriceNum']/text()").get());
taobao.setRatecounter(page.getHtml().xpath("//strong[@id='J_RateCounter']/text()").get());
taobao.setSellcounter(page.getHtml().xpath("//strong[@id='J_SellCounter']/text()").get());
// 把對象存入數據庫
taobaoDao.addTaobao(taobao);
// 把對象輸出控制檯
System.out.println(taobao.toString());
}
}
public static void main(String[] args) {
Spider.create(new TaobaoPageProcessor()).setDownloader(new Downloader() {
@Override
public void setThread(int threadNum) {
}
@Override
public Page download(Request request, Task task) {
return GetAjaxHtml.download(request);
}
}).addUrl("https://s.taobao.com/list?q=%E5%A4%B9%E5%85%8B&cat=50344007&style=grid&seller_type=taobao").thread(5).run();
}
}