欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 爬蟲數(shù)據(jù)異步加載如何解決

 更新時(shí)間:2019年10月17日 09:30:02   作者:平頭哥的技術(shù)博文  
這篇文章主要介紹了Java 爬蟲遇上數(shù)據(jù)異步加載,試試這兩種辦法!問題如何解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這是 Java 爬蟲系列博文的第三篇,在上一篇Java 爬蟲如何爬取需要登錄的網(wǎng)站,該怎么辦? 中,我們簡(jiǎn)單的講解了爬蟲時(shí)遇到登錄問題的解決辦法,在這篇文章中我們一起來聊一聊爬蟲時(shí)遇到數(shù)據(jù)異步加載的問題,這也是爬蟲中常見的問題。

現(xiàn)在很多都是前后端分離項(xiàng)目,這會(huì)使得數(shù)據(jù)異步加載問題更加突出,所以你在爬蟲時(shí)遇到這類問題不必驚訝,不必慌張。對(duì)于這類問題的解決辦法總體來說有以下兩種:

1、內(nèi)置一個(gè)瀏覽器內(nèi)核

內(nèi)置瀏覽器就是在抓取的程序中,啟動(dòng)一個(gè)瀏覽器內(nèi)核,使我們獲取到 js 渲染后的頁面,這樣我們就跟采集靜態(tài)頁面一樣了。這種工具常用的有以下三種:

  • Selenium
  • HtmlUnit
  • PhantomJs

這些工具都能幫助我們解決數(shù)據(jù)異步加載的問題,但是他們都存在缺陷,那就是效率不高而且不穩(wěn)定。

2、反向解析法

什么是反向解析法呢?我們 js 渲染頁面的數(shù)據(jù)是通過 Ajax 的方式從后端獲取的,我們只需要找到對(duì)應(yīng)的 Ajax 請(qǐng)求連接就 OK,這樣我們就獲取到了我們需要的數(shù)據(jù),反向解析法的好處就是這種方式獲取的數(shù)據(jù)都是 json 格式的數(shù)據(jù),解析起來也比較方便,另一個(gè)好處就是相對(duì)頁面來說,接口的變化概率更小。同樣它有兩個(gè)不足之處,一個(gè)是在 Ajax 時(shí)你需要有耐心有技巧,因?yàn)槟阈枰谝淮笸普?qǐng)求中找到你想要的,另一個(gè)不足的地方就是對(duì) JavaScript 渲染的頁面束手無策。

上面就是異步數(shù)據(jù)加載的兩種解決辦法,為了加深大家的理解和在項(xiàng)目中如何使用,我以采集網(wǎng)易要聞為例,網(wǎng)易新聞地址:https://news.163.com/ 。利用上訴的兩種方式來獲取網(wǎng)易要聞的新聞列表。網(wǎng)易要聞如下:

內(nèi)置瀏覽器 Selenium 方式

Selenium 是一個(gè)模擬瀏覽器,進(jìn)行自動(dòng)化測(cè)試的工具,它提供一組 API 可以與真實(shí)的瀏覽器內(nèi)核交互。在自動(dòng)化測(cè)試上使用的比較多,爬蟲時(shí)解決異步加載也經(jīng)常使用它,我們要在項(xiàng)目中使用 Selenium ,需要做兩件事:

1、引入 Selenium 的依賴包,在 pom.xml 中添加

<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
 <groupId>org.seleniumhq.selenium</groupId>
 <artifactId>selenium-java</artifactId>
 <version>3.141.59</version>
</dependency>

2、下載對(duì)應(yīng)的 driver,例如我下載的 chromedriver,下載地址為:https://npm.taobao.org/mirrors/chromedriver/,下載后,需要將 driver 的位置寫到 Java 的環(huán)境變量里,例如我直接放在項(xiàng)目下,所以我的代碼為:

System.getProperties().setProperty("webdriver.chrome.driver", "chromedriver.exe");

完成上面兩步之后,我們就可以來編寫使用 Selenium 采集網(wǎng)易要聞啦。具體代碼如下:

/**
 * selenium 解決數(shù)據(jù)異步加載問題
 * https://npm.taobao.org/mirrors/chromedriver/
 *
 * @param url
 */
public void selenium(String url) {
 // 設(shè)置 chromedirver 的存放位置
 System.getProperties().setProperty("webdriver.chrome.driver", "chromedriver.exe");
 // 設(shè)置無頭瀏覽器,這樣就不會(huì)彈出瀏覽器窗口
 ChromeOptions chromeOptions = new ChromeOptions();
 chromeOptions.addArguments("--headless");

 WebDriver webDriver = new ChromeDriver(chromeOptions);
 webDriver.get(url);
 // 獲取到要聞新聞列表
 List<WebElement> webElements = webDriver.findElements(By.xpath("http://div[@class='news_title']/h3/a"));
 for (WebElement webElement : webElements) {
 // 提取新聞連接
 String article_url = webElement.getAttribute("href");
 // 提取新聞標(biāo)題
 String title = webElement.getText();
 if (article_url.contains("https://news.163.com/")) {
  System.out.println("文章標(biāo)題:" + title + " ,文章鏈接:" + article_url);
 }
 }
 webDriver.close();
}

運(yùn)行該方法,得到結(jié)果如下:

我們使用 Selenium 已經(jīng)正確的提取到了網(wǎng)易要聞的列表新聞。

反向解析法

反向解析法就是獲取到 Ajax 異步獲取數(shù)據(jù)的鏈接,直接獲取到新聞數(shù)據(jù)。如果沒有技巧的話,查找 Ajax 的過程將非常痛苦,因?yàn)橐粋€(gè)頁面加載的鏈接太多了,看看網(wǎng)易要聞的 network:

有幾百條的請(qǐng)求,該如何查找到是哪條請(qǐng)求獲取的要聞數(shù)據(jù)呢?你不嫌麻煩的話,可以一個(gè)一個(gè)的去點(diǎn),肯定能夠查找到的,另一種快捷的辦法是利用 network 的搜索功能,如果你不知道搜索按鈕,我在上圖已經(jīng)圈出來啦,我們?cè)谝勚须S便復(fù)制一個(gè)新聞標(biāo)題,然后檢索一下,就可以獲取到結(jié)果,如下圖所示:

這樣我們就快速的獲取到了要聞數(shù)據(jù)的請(qǐng)求鏈接,鏈接為:https://temp.163.com/special/00804KVA/cm_yaowen.js?callback=data_callback,訪問該鏈接,查看該鏈接返回的數(shù)據(jù),如下圖所示:

從數(shù)據(jù)我們可以看出,我們需要的數(shù)據(jù)都在這里啦,所以我們只需要解析這段數(shù)據(jù)接可以啦,要從這段數(shù)據(jù)中解析出新聞標(biāo)題和新聞鏈接,有兩種方式,一種是正則表達(dá)式,另一種是將該數(shù)據(jù)轉(zhuǎn)成 json 或者 list。這里我選擇第二種方式,利用 fastjson 將返回的數(shù)據(jù)轉(zhuǎn)換成 JSONArray 。所以我們是要引入 fastjson ,在 pom.xml 中引入 fastjson 依賴:

<dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>fastjson</artifactId>
 <version>1.2.59</version>
</dependency>

除了引入 fastjson 依賴外,我們?cè)谵D(zhuǎn)換前還需要對(duì)數(shù)據(jù)進(jìn)行簡(jiǎn)單的處理,因?yàn)楝F(xiàn)在的數(shù)據(jù)并不符合 list 的格式,我們需要去掉 data_callback( 和最后面的 )。具體反向解析獲取網(wǎng)易要聞的代碼如下:

/**
 * 使用反向解析法 解決數(shù)據(jù)異步加載的問題
 *
 * @param url
 */
public void httpclientMethod(String url) throws IOException {

 CloseableHttpClient httpclient = HttpClients.createDefault();
 HttpGet httpGet = new HttpGet(url);
 CloseableHttpResponse response = httpclient.execute(httpGet);
 if (response.getStatusLine().getStatusCode() == 200) {
 HttpEntity entity = response.getEntity();
 String body = EntityUtils.toString(entity, "GBK");
 // 先替換掉最前面的 data_callback(
 body = body.replace("data_callback(", "");
 // 過濾掉最后面一個(gè) )右括號(hào)
 body = body.substring(0, body.lastIndexOf(")"));
 // 將 body 轉(zhuǎn)換成 JSONArray
 JSONArray jsonArray = JSON.parseArray(body);
 for (int i = 0; i < jsonArray.size(); i++) {
  JSONObject data = jsonArray.getJSONObject(i);
  System.out.println("文章標(biāo)題:" + data.getString("title") + " ,文章鏈接:" + data.getString("docurl"));
 }
 } else {
 System.out.println("處理失敗?。?!返回狀態(tài)碼:" + response.getStatusLine().getStatusCode());
 }

}

編寫 main 方法,執(zhí)行上面的方法,需要注意的地方是:這時(shí)候傳入的鏈接為https://temp.163.com/special/00804KVA/cm_yaowen.js?callback=data_callback 而不是 https://news.163.com/。得到如下結(jié)果:

兩種方法都成功的獲取到了網(wǎng)易要聞異步加載的新聞列表,對(duì)于這兩種方法的選取,我個(gè)人的傾向是使用反向解析法,因?yàn)樗男阅芎头€(wěn)定是都要比內(nèi)置瀏覽器內(nèi)核靠譜,但是對(duì)于一些使用 JavaScript 片段渲染的頁面,內(nèi)置瀏覽器又更加靠譜。所以根據(jù)具體情況選擇吧。

源代碼:源代碼

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入了解Spring的Bean生命周期

    深入了解Spring的Bean生命周期

    這篇文章主要為大家介紹了Spring的Bean生命周期,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的可以學(xué)習(xí)一下
    2022-01-01
  • Gradle 創(chuàng)建Task的多種方法

    Gradle 創(chuàng)建Task的多種方法

    本文主要介紹了Gradle 創(chuàng)建Task的多種方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • java時(shí)間 java.util.Calendar深入分析

    java時(shí)間 java.util.Calendar深入分析

    這篇文章主要介紹了java時(shí)間 java.util.Calendar深入分析的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • win10下定時(shí)運(yùn)行與開機(jī)自啟動(dòng)jar包的方法記錄

    win10下定時(shí)運(yùn)行與開機(jī)自啟動(dòng)jar包的方法記錄

    這篇文章主要給大家介紹了關(guān)于win10下定時(shí)運(yùn)行與開機(jī)自啟動(dòng)jar包的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • ReentrantLock條件變量使多個(gè)線程順序執(zhí)行

    ReentrantLock條件變量使多個(gè)線程順序執(zhí)行

    這篇文章主要為大家介紹了ReentrantLock條件變量使多個(gè)線程順序執(zhí)行,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • java利用正則表達(dá)式處理特殊字符的方法實(shí)例

    java利用正則表達(dá)式處理特殊字符的方法實(shí)例

    這篇文章主要給大家介紹了關(guān)于java利用正則表達(dá)式處理特殊字符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java 如何調(diào)用long的最大值和最小值

    Java 如何調(diào)用long的最大值和最小值

    這篇文章主要介紹了Java 如何調(diào)用long的最大值和最小值的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 深入淺析SpringBoot自動(dòng)配置原理

    深入淺析SpringBoot自動(dòng)配置原理

    本文給大家介紹SpringBoot自動(dòng)配置原理解析,springboot使用的是2.3.1版本源碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-10-10
  • java常用工具類 UUID、Map工具類

    java常用工具類 UUID、Map工具類

    這篇文章主要為大家詳細(xì)介紹了Java常用工具類,包括UUID工具類、Map工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 解決Java?API不能遠(yuǎn)程訪問HBase的問題

    解決Java?API不能遠(yuǎn)程訪問HBase的問題

    這篇文章主要介紹了解決Java?API不能遠(yuǎn)程訪問HBase的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06

最新評(píng)論