如何用JAVA爬取AJAX加載后的頁(yè)面(利用phantomjs)【以天眼查為例】

之前

之前利用Jsoup做了個(gè)小DEMO爬取百度免費(fèi)API(* http://apistore.baidu.com/ )潜支,很簡(jiǎn)單,用Jsoup就可以做到柿汛,因?yàn)轫?yè)面加載后的數(shù)據(jù)填充到html里面冗酿,此時(shí)查看源代碼會(huì)看見(jiàn)數(shù)據(jù)都在源代碼里面,這時(shí)候可以利用Jsoup爬取苛茂,前幾天有個(gè)需求要爬取天眼查的數(shù)據(jù)( http://www.tianyancha.com *)已烤,自以為和之前做的DEMO一樣,不難妓羊,就利用原來(lái)的DEMO改改,之后居然獲取不到想要的稍计。

需求:搜索(條件包括搜索框躁绸,注冊(cè)資本,地區(qū))

以下是我將要爬取的頁(yè)面:


搜索:有限

習(xí)慣性審查一下要爬取的元素:


這部分是主頁(yè)面

胸有成竹代碼就出來(lái):

Document doc = Jsoup.connect("http://www.tianyancha.com/search?key=有限").ignoreHttpErrors(true).timeout(100000).get();
System.out.println(doc.body());

執(zhí)行--》

<body ng-class="isFromMac ? '':'windows-modal'"> 
 <!-- <body class="b-c13" ng-class="{'windows-modal':!isFromMac, 'bodyOverHidden':bodyHidden, 'bodyOverShow':!bodyHidden}"> --> 
 <div id="loading" class="loading" loading=""></div> 
 <div id="ng-view" ng-view=""></div> 
 <!-- banner --> 
 <div ng-cloak="" ng-controller="bannerCtrl"> 
  <!-- ![](http://static.tianyancha.com/wap/images/element.png?_v=)</img> --> 
  <div ng-cloak="" ng-if="isPCClient" class="bottom-banner"> 
   <!-- <div class="bottom-banner-body"   ng-show="showBanner" >
            ![app下載](http://upload-images.jianshu.io/upload_images/3810137-5c0f1e424921f6e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
            <div class="bottom-banner-qrcode"  >
                <img class="bottom-banner-qrcode-img" alt="qrcode"
                     src="http://static.tianyancha.com/wap/images/banner-bottom-qrcode.png">
            </div>
            <img class="bottom-banner-close" alt="close"
                 ng-click="ctrlBanner(false);"
                 src="http://static.tianyancha.com/wap/images/banner-bottom-close.png">
        </div> --> 
   <div class="bottom-banner-body2" ng-if="showBanner"> 
    <div class="bottom-banner-box2 company_container"> 
     ![](http://upload-images.jianshu.io/upload_images/3810137-a12c9c8e1c375522.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
     <div class="code_box"> 
      ![](http://upload-images.jianshu.io/upload_images/3810137-e7840a271fd37e8e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
     </div> 
     ![](http://upload-images.jianshu.io/upload_images/3810137-2dc1551260095554.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
     ![](http://upload-images.jianshu.io/upload_images/3810137-2f8c0c671b889cd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
    </div> 
   </div> 
   ![app下載](http://upload-images.jianshu.io/upload_images/3810137-41c6fa56e3e5e7e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
   <!-- <div ng-show="showAdvertise" advertise-banner></div> --> 
  </div> 
  <div ng-show="!isPCClient&&!isTYCClient&&!isWebAppClient"> 
   <div ng-cloak="" ng-show="!showBannerMobile" style="position: fixed;left: 0;bottom:90px;" ng-click="closeClick(showBannerMobile);"> 
    ![下載天眼查專(zhuān)業(yè)版APP](http://upload-images.jianshu.io/upload_images/3810137-93ed2e33708d2d46.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
   </div> 
   <div class="bottom-banner-mobile" ng-cloak="" ng-show="showBannerMobile"> 
    ![下載天眼查專(zhuān)業(yè)版APP](http://upload-images.jianshu.io/upload_images/3810137-0726860681c21931.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
    ![下載天眼查專(zhuān)業(yè)版APP](http://upload-images.jianshu.io/upload_images/3810137-fd3b233ccd8b1c0a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
    <span> <a  target="_blank"> ![下載天眼查專(zhuān)業(yè)版APP](http://upload-images.jianshu.io/upload_images/3810137-d73cd12dbd35be37.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) </a> </span> 
    ![關(guān)閉](http://upload-images.jianshu.io/upload_images/3810137-f2a78be96ebe8a57.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
   </div> 
  </div> 
 </div> 
 <script>var gdt_tracker=gdt_tracker||[];gdt_tracker.push(["set_source_id","33937"]);!function(){var e=navigator.userAgent;if(e.indexOf("ignore")<0){var t=document,r=t.getElementsByTagName("head")[0],a=t.createElement("script");a.async=!0;a.src="http://qzs.qq.com/qzone/biz/res/gt.js";r&&r.insertBefore(a,r.firstChild)}}();</script> 
 <script>var _hmt=_hmt||[];!function(){var e=navigator.userAgent;if(e.indexOf("ignore")<0){var t=document.createElement("script");t.src="http://#/hm.js?e92c8d65d92d534b0fc290df538b4758";var r=document.getElementsByTagName("script")[0];r.parentNode.insertBefore(t,r)}}();</script> 
 <!-- <script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="http://#/hm.js?9c350b9e33b321dffebc9cc49db07828";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}();</script> --> 
 <!-- Piwik --> 
 <script type="text/javascript">var _paq=_paq||[];_paq.push(["trackPageView"]);_paq.push(["enableLinkTracking",!0]);!function(){var e="http://www.tianyancha.com/piwik/";_paq.push(["setTrackerUrl",e+"piwik.php"]);_paq.push(["setSiteId",1]);var a=document,p=a.createElement("script"),t=a.getElementsByTagName("script")[0];p.type="text/javascript";p.async=!0;p.defer=!0;p.src=e+"piwik.js";t.parentNode.insertBefore(p,t)}();</script> 
 <noscript>
  <p>[站外圖片上傳中……(13)]</p>
 </noscript> 
 <!-- End Piwik Code --> 
 <!--<script src="http://api.map.baidu.com/api?v=2.0&ak=E1r6u1CD9SzZ08IxP32bNjgz"></script>-->   
 <!--coolie@1.0.8-->
</body>

WTF臣嚣?

只有這點(diǎn)東西净刮?明明我審查元素的時(shí)候有那么多?為什么抓取出來(lái)就這么點(diǎn)硅则?這不科學(xué)淹父。

爬取的2個(gè)辦法:

  • 利用Jsoup爬取
  • 利用Ajax請(qǐng)求返回的數(shù)據(jù)

其一不行,取其二
通過(guò)Ajax請(qǐng)求數(shù)據(jù)怎虫,再填充到body里面暑认,于是研究Ajax請(qǐng)求,通過(guò)Chrome的NetWork可以抓到:

NetWork

這個(gè)接口返回的就是列表的數(shù)據(jù)大审,欣喜若狂蘸际,這也太簡(jiǎn)單了,雙擊訪問(wèn)出現(xiàn):

錯(cuò)誤

WTF2

這徒扶。粮彤。到底是咋回事
在搜索了很多文章后發(fā)現(xiàn),這個(gè)網(wǎng)站本來(lái)就是從各大政府網(wǎng)站爬取過(guò)來(lái)的數(shù)據(jù)姜骡,哪能那么容易就輕松被別人爬取走导坟。況且:

反爬蟲(chóng)工程師

失望中另辟蹊徑

失望中又想到另外的辦法,既然不能通過(guò)Jsoup去爬取圈澈,那么是不是有方法可以模擬人為訪問(wèn)惫周,訪問(wèn)后加載完所有的css和js,等數(shù)據(jù)都返回士败,再爬取闯两,這不就可以了褥伴。
開(kāi)啟搜索引擎一陣搜:

  1. HttpUnit (http://blog.csdn.net/hfhwfw/article/details/37838615)
  1. HtmlUnit (https://my.oschina.net/MiniBu/blog/140729)
  2. WebDriver (https://my.oschina.net/dyhunter/blog/94090)

以上方法都是做自動(dòng)化測(cè)試用的,根本不是用來(lái)爬取數(shù)據(jù)的漾狼,所以兼容性不能不是很好重慢。各種嘗試都沒(méi)有得到想要的效果。
最后發(fā)現(xiàn)了phantomjs ( http://phantomjs.org/ )逊躁。
下載phantomjs后終端就行似踱,加入環(huán)境變量自行百度,此處不再多說(shuō)稽煤。

windows下載對(duì)應(yīng)的phantomjs.exe

運(yùn)行:

/User/music-man/Downloads/phantomjs/phantomjs /User/music-man/Downloads/phantomjs/code.js http://www.tianyancha.com/search?key=有限

注意中間的空格核芽。第一個(gè)是phantomjs,第二個(gè)是code.js的路徑酵熙,第三個(gè)是爬取的路徑轧简。
code.js

system = require('system')  
address = system.args[1];
var page = require('webpage').create();  
var url = address;  
page.open(url, function (status) {  
    //Page is loaded!  
    if (status !== 'success') {  
        console.log('Unable to post!');  
    } else {  
            console.log(page.content);
            phantom.exit();
    } 
  });   

此時(shí)終端執(zhí)行命令,發(fā)現(xiàn)整個(gè)頁(yè)面已經(jīng)爬取下來(lái)匾二。
接下來(lái)就是如何與Java結(jié)合了哮独。
執(zhí)行命令Java可以這么做

Runtime rt = Runtime.getRuntime();
String exec = "/Users/music-man/Downloads/phantomjs/phantomjs /Users/music-man/Downloads/phantomjs/code.js " + url;
Process p = rt.exec(exec);
InputStream is = p.getInputStream();

這樣就可以獲得輸入流了,獲得輸入流之后想要怎么操作就簡(jiǎn)單了吧察藐。
獲取了文件流皮璧,想操作dom,如何操作呢分飞?
看了一下Jsoup悴务,發(fā)現(xiàn)


輸入流轉(zhuǎn)Jsoup
public static Document parse(InputStream in, String charsetName, String baseUri) 

第一個(gè)參數(shù)是輸入流,第二個(gè)是字符集譬猫,第三個(gè)是地址:

Document doc = Jsoup.parse(is, "UTF-8", url);

獲取到Document再操作dom元素就很明了了讯檐。
最后用JFrame做了個(gè)界面

不穩(wěn)定

執(zhí)行起來(lái)發(fā)現(xiàn)不穩(wěn)定,有時(shí)候能爬取到頁(yè)面删窒,有時(shí)候就會(huì)失敗裂垦,讓我以為是網(wǎng)站做的限制,后來(lái)發(fā)現(xiàn)多次重復(fù)爬取效率過(guò)快的話網(wǎng)站會(huì)讓輸入驗(yàn)證碼肌索,導(dǎo)致卡住蕉拢。

解決

爬取不到我初步懷疑是因?yàn)榕廊〉臅r(shí)候頁(yè)面還沒(méi)加載完畢,就進(jìn)行抓取诚亚,有時(shí)候網(wǎng)速快晕换,加載好了就能抓取到,有時(shí)候沒(méi)有加載好站宗,爬取失敗闸准。看了下phantomjs例子(https://github.com/ariya/phantomjs/blob/master/examples/page_events.js)
發(fā)現(xiàn)可以采用js的方法setTimeout
最終code.js改為

system = require('system')  
address = system.args[1];
var page = require('webpage').create();  
var url = address;  
page.open(url, function (status) {  
    //Page is loaded!  
    if (status !== 'success') {  
        console.log('Unable to post!');  
    } else {  
            window.setTimeout(function () {
              page.render("test1.png");  //截圖
              console.log(page.content);
              phantom.exit();
          }, 5000);   
    } 
  });   

增加了setTimeout方法后梢灭,等待5s差不多執(zhí)行完頁(yè)面和js夷家,此時(shí)再去抓取頁(yè)面蒸其,發(fā)現(xiàn)成功率大大提高。

(2017年12月05日 刪除圖片库快,泄漏隱私了)

抓取到后再把需要的寫(xiě)出文件就可以了摸袁。

轉(zhuǎn)載請(qǐng)注明出處,謝謝义屏。碼了一個(gè)多小時(shí)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末靠汁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子闽铐,更是在濱河造成了極大的恐慌蝶怔,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兄墅,死亡現(xiàn)場(chǎng)離奇詭異踢星,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)隙咸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)斩狱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扎瓶,你說(shuō)我怎么就攤上這事∶谇梗” “怎么了概荷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)碌燕。 經(jīng)常有香客問(wèn)我误证,道長(zhǎng),這世上最難降的妖魔是什么修壕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任愈捅,我火速辦了婚禮,結(jié)果婚禮上慈鸠,老公的妹妹穿的比我還像新娘蓝谨。我一直安慰自己,他們只是感情好青团,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布譬巫。 她就那樣靜靜地躺著,像睡著了一般督笆。 火紅的嫁衣襯著肌膚如雪芦昔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天娃肿,我揣著相機(jī)與錄音咕缎,去河邊找鬼珠十。 笑死,一個(gè)胖子當(dāng)著我的面吹牛凭豪,可吹牛的內(nèi)容都是我干的焙蹭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼墅诡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼壳嚎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起末早,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤烟馅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后然磷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體郑趁,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年姿搜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了寡润。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舅柜,死狀恐怖梭纹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情致份,我是刑警寧澤变抽,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站氮块,受9級(jí)特大地震影響绍载,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滔蝉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一击儡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝠引,春花似錦阳谍、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至谅年,卻和暖如春茧痒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背融蹂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工旺订, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弄企,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓区拳,卻偏偏與公主長(zhǎng)得像拘领,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子樱调,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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