2016-10-04 18 views
1

我已經看到了一些將這個askee引用到其他庫(如phantom.js)的答案,但我在這裏想知道它是否在所有可能的只是在node.js中做到這一點?Node.js:請求頁面並允許頁面在構建之前構建

考慮到我的代碼如下。它請求一個使用request的網頁,然後使用cheerio它探索了dom到scrape的數據頁面。它的工作完美無缺,如果一切按計劃進行,我相信它會輸出一個我想像中的文件。

問題是,page I am requesting爲了湊,建表IM看着異步使用AJAX兩種或JSONP,我不是很確定頁面如何.JSP工作。
所以在這裏我試圖找到一種方法來「加載」這些數據,然後再爲我的新文件擦除數據。

var cheerio = require('cheerio'), 
    request = require('request'), 
    fs = require('fs'); 

// Go to the page in question 
request({ 
    method: 'GET', 
    url: 'http://www1.chineseshipping.com.cn/en/indices/cbcfinew.jsp' 
}, function(err, response, body) { 
    if (err) return console.error(err); 
    // Tell Cherrio to load the HTML 
    $ = cheerio.load(body); 


    // Create an empty object to write to the file later  
    var toSort = {} 

    // Itterate over DOM and fill the toSort object 
    $('#emb table td.list_right').each(function() { 
     var row = $(this).parent();  
     toSort[$(this).text()] = { 
      [$("#lastdate").text()]: $(row).find(".idx1").html(), 
      [$("#currdate").text()]: $(row).find(".idx2").html()    
     } 
    }); 

    //Write/overwrite a new file 
    var stream = fs.createWriteStream("/tmp/shipping.txt"); 
    var toWrite = ""; 

    stream.once('open', function(fd) { 
     toWrite += "{\r\n" 
     for(i in toSort){ 
      toWrite += "\t" + i + ": { \r\n"; 
       for(j in toSort[i]){ 
        toWrite += "\t\t" + j + ":" + toSort[i][j] + ",\r\n";    
       }    
      toWrite += "\t" + "}, \r\n"; 
     } 
     toWrite += "}" 

     stream.write(toWrite) 
     stream.end(); 
    }); 
}); 

預期結果是一個文本文件,其格式信息格式類似於JSON對象。

它應該是這個樣子的這

"QINHUANGDAO - GUANGZHOU (50,000-60,000DWT)": { 
     "2016-09-29": 26.7, 
    "2016-09-30": 26.8, 
}, 

不同的實例,但由於名稱是不加載異步的唯一的事情,(日期和值是異步),我得到一個搞砸對象。

我試過其實只是在代碼的不同位置設置了setTimeout。腳本只會被開發者觸及,如果腳本失敗了幾次,腳本可以多次運行腳本。所以雖然不理想,但即使setTimeout(最多5秒)也足夠好。

原來settimeouts不起作用。我懷疑,一旦我請求這個頁面,當我收到它時,我就會停留在頁面的快照上,而實際上我沒有看到一個我可以等待加載它的動態內容的活動。

我不知道如何攔截軟件包,因爲他們來了,但我不明白HTTP足夠好,知道從哪裏開始。

回答

1

即使將它增加到一小時,setTimeout也不會有任何區別。這裏的問題是,你正在對這個url做出請求: http://www1.chineseshipping.com.cn/en/indices/cbcfinew.jsp

和他們的服務器返回的html,並在這個html中有js和css的導入。這是你的情況的結束,你只需要html就可以了。相反,瀏覽器知道如何使用和解析html文檔,所以它能夠理解javascript腳本並執行/運行它們,這正是您的問題。您的程序無法理解與HTML內容有關的內容。你需要找到或寫一個能夠運行JavaScript的刮板。我剛剛發現這個類似的問題在計算器上: Web-scraping JavaScript page with Python

那傢伙建議https://github.com/niklasb/dryscrape,似乎這個工具能夠運行javascript。它是用python編寫的。

+0

你的解釋鞏固了我的懷疑,謝謝。雖然我不能使用python,但我會研究如何解析頁面。也許我可以考慮託管網頁並傳輸結果或其他東西 – NachoDawg

+0

如果你在谷歌上搜索類似於:node.js刮板框架,你會得到一些結果。這篇文章可能會有所幫助: http://blog.webkid.io/nodejs-scraping-libraries/ 如果你想你可以接受的答案:) –

+1

隨着你最近的評論中的鏈接,接受似乎適當。考慮編輯它到答案:) – NachoDawg

1

您試圖抓取不包含所需數據的原始頁面。 加載頁面時,瀏覽器評估它包含的JS代碼,並且此代碼知道在何處以及如何獲取數據。

第一個選項是評估相同的代碼,如PhantomJS做的。

另一方面(您似乎對此感興趣)是調查網頁的網絡活動並瞭解您應該執行哪些附加請求以獲取所需的數據。 在你的情況,它們是:

http://index.chineseshipping.com.cn/servlet/cbfiDailyGetContrast?SpecifiedDate=&jc=jsonp1475577615267&_=1475577619626

http://index.chineseshipping.com.cn/servlet/allGetCurrentComposites?date=Tue%20Oct%2004%202016%2013:40:20%20GMT+0300%20(MSK)&jc=jsonp1475577615268&_=1475577620325

在這兩個請求:

所以被調用,在http://www1.chineseshipping.com.cn/en/indices/cbcfinew.jsp再殺表模板,進行兩個額外request是你可以將它們組合成您在瀏覽器中看到的數據結構相同。