曾幾什麼時候,動態頁面(ajax,內部js二次渲染等等)信息提取一直都是爬蟲開發者的心痛點,一句話,實在沒有合適的工具。尤爲在Java裏面,像htmlunit這種工具都算得上解析動態頁面的神器了,可是他依然不夠完備,達不到瀏覽器級的解析效果,遇到稍微複雜點的頁面就不行了。在經歷的各類痛與恨後,筆者決定乾脆開發一款專爲應對抓取,監控,以及測試這類場景使用的動態頁面渲染處理服務器。要達到瀏覽器級的效果,那必須基於瀏覽器內核來開發,幸運的是咱們有開源的webkit,更爲幸運的是咱們有對開發者更爲友好的QtWebkit。因此SeimiAgent就這樣誕生了。html
SeimiAgent是基於QtWebkit開發的可在服務器端後臺運行的一個webkit服務,能夠經過SeimiAgent提供的http接口向SeimiAgent發送一個load請求(需求加載的URL以及對這個頁面接受的渲染時間或是使用什麼代理等參數),經過SeimiAgent去加載並渲染想要處理的動態頁面,而後將渲染好的頁面直接返給調用方進行後續處理,因此運行的SeimiAgent服務是與語言無關的,任何一種語言或框架均可以經過SeimiAgent提供的標準http接口來獲取服務。SeimiAgent的加載渲染環境都是通用瀏覽器級的,因此不用擔憂他對動態頁面的處理能力。目前SeimiAgent只支持返回渲染好的HTML文檔,後續會增長圖像快照已經PDF的支持,方便更爲多樣化的使用需求。git
SeimiCrawler是一個敏捷的,獨立部署的,支持分佈式的Java爬蟲框架,但願能在最大程度上下降新手開發一個可用性高且性能不差的爬蟲系統的門檻,以及提高開發爬蟲系統的開發效率。在SeimiCrawler的世界裏,絕大多數人只需關心去寫抓取的業務邏輯就夠了,其他的Seimi幫你搞定。設計思想上SeimiCrawler受Python的爬蟲框架Scrapy啓發很大,同時融合了Java語言自己特色與Spring的特性,並但願在國內更方便且廣泛的使用更有效率的XPath解析HTML,因此SeimiCrawler默認的HTML解析器是JsoupXpath(獨立擴展項目,非jsoup自帶),默認解析提取HTML數據工做均使用XPath來完成(固然,數據處理亦能夠自行選擇其餘解析器)。github
下載解壓縮就不表了,上面的動態圖中也有演示,下載地址能夠到SeimiAgent主頁找到。進到SeimiAgent的bin目錄,執行:web
./SeimiAgent -p 8000
這是啓動SeimiAgent服務並監聽8000端口。接下來實際上就可使用任何語言經過http請求發送加載頁面的請求,而後獲得渲染後的結果。固然咱們這裏是要介紹SeimiCrawler是如何整合使用SeimiAgent的。ajax
SeimiCrawler在v0.3.0版本中已經內置支持了SeimiAgent,只須要開發者配置好SeimiAgent的地址和端口,而後在生成具體Request時選擇是否要提交給SeimiAgent,而且指定如何遞交。直接上個完整例子在註釋中說明吧:spring
package cn.wanghaomiao.crawlers; import cn.wanghaomiao.seimi.annotation.Crawler; import cn.wanghaomiao.seimi.def.BaseSeimiCrawler; import cn.wanghaomiao.seimi.struct.Request; import cn.wanghaomiao.seimi.struct.Response; import cn.wanghaomiao.xpath.model.JXDocument; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; /** * 這個例子演示如何使用SeimiAgent進行復雜動態頁面信息抓取 * @author 汪浩淼 et.tw@163.com * @since 2016/4/14. */ @Crawler(name = "seimiagent") public class SeimiAgentDemo extends BaseSeimiCrawler{ /** * 在resource/config/seimi.properties中配置方便更換,固然也能夠自行根據狀況使用本身的統一配置中心等服務。這裏配置SeimiAgent服務所在地址。 */ @Value("${seimiAgentHost}") private String seimiAgentHost; //SeimiAgent監聽的端口好,如上文中的8000 @Value("${seimiAgentPort}") private int seimiAgentPort; @Override public String[] startUrls() { return new String[]{"https://www.baidu.com"}; } @Override public String seimiAgentHost() { return this.seimiAgentHost; } @Override public int seimiAgentPort() { return this.seimiAgentPort; } @Override public void start(Response response) { Request seimiAgentReq = Request.build("https://www.souyidai.com","getTotalTransactions") .useSeimiAgent() // 告訴SeimiAgent針對這個請求是否使用cookie,若是沒有設置使用當前Crawler關於cookie使用條件做爲默認值。 //.setSeimiAgentUseCookie(true) // 設置所有load完成後給SeimiAgent多少時間用於執行js並渲染頁面,單位爲毫秒 .setSeimiAgentRenderTime(5000); push(seimiAgentReq); } /** * 獲取搜易貸首頁總成交額 * @param response */ public void getTotalTransactions(Response response){ JXDocument doc = response.document(); try { String trans = StringUtils.join(doc.sel("//div[@class='homepage-amount']/div[@class='number font-arial']/div/span/text()"),""); logger.info("Final Res:{}",trans); } catch (Exception e) { e.printStackTrace(); } } }
配置文件seimi.properties
apache
seimiAgentHost=127.0.0.1 seimiAgentPort=8000
啓動瀏覽器
public class Boot { public static void main(String[] args){ Seimi s = new Seimi(); s.start("seimiagent"); } }
SeimiCrawler啓動後就能夠看到你想要的搜易貸交易總額了。服務器