在之前的系列文章中介紹了如何使用httpclient抓取頁面html以及如何用jsoup分析html源檔案內容得到我們想要的資料,但是有時候通過這兩種方式不能正常抓取到我們想要的資料,比如看如下例子,
1.需求場景:
想要抓取股票的最新價格,頁面F12資訊如下:

按照前面的方式,爬取的代碼如下:
/**
* @description: 爬取股票的最新股價
* @author: JAVA開發老菜鳥
* @date: 2021-10-16 21:47
*/
public class StockPriceSpider {
Logger logger = LoggerFactory.getLogger(this.getClass());
public static void main(String[] args) {
StockPriceSpider stockPriceSpider = new StockPriceSpider();
String html = stockPriceSpider.httpClientProcess();
stockPriceSpider.jsoupProcess(html);
}
private String httpClientProcess() {
String html = "";
String uri = "http://quote.eastmoney.com/sh600036.html";
//1.生成httpclient,相當于該打開一個瀏覽器
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
//2.創建get請求,相當于在瀏覽器地址欄輸入 網址
HttpGet request = new HttpGet(uri);
try {
request.setHeader("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36");
request.setHeader("accept", "application/json, text/javascript, */*; q=0.01");
// HttpHost proxy = new HttpHost("3.211.17.212", 80);
// RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
// request.setConfig(config);
//3.執行get請求,相當于在輸入地址欄后敲回車鍵
response = httpClient.execute(request);
//4.判斷回應狀態為200,進行處理
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
//5.獲取回應內容
HttpEntity httpEntity = response.getEntity();
html = EntityUtils.toString(httpEntity, "utf-8");
logger.info("訪問{} 成功,回傳頁面資料{}", uri, html);
} else {
//如果回傳狀態不是200,比如404(頁面不存在)等,根據情況做處理,這里略
logger.info("訪問{},回傳狀態不是200", uri);
logger.info(EntityUtils.toString(response.getEntity(), "utf-8"));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//6.關閉
HttpClientUtils.closeQuietly(response);
HttpClientUtils.closeQuietly(httpClient);
}
return html;
}
private void jsoupProcess(String html) {
Document document = Jsoup.parse(html);
Element price = document.getElementById("price9");
logger.info("股價為:>>> {}", price.text());
}
}
運行結果:

納尼,股價為"-" ?不可能,
之所以爬不到正確的結果,是因為這個值在網站上是通過異步加載渲染的,因此不能正常獲取,
2.java爬取異步加載的資料的方法
那如何爬取異步加載的資料呢?通常有兩種做法:
2.1內置瀏覽器內核
內置瀏覽器就是在抓取的程式中啟動一個瀏覽器內核,使我們獲取到 js 渲染后的頁面就和靜態頁面一樣,常用的內核有
- Selenium
- PhantomJs
- HtmlUnit
這里我選了Selenium,它是一個模擬瀏覽器,是進行自動化測驗的工具,它提供一組 API 可以與真實的瀏覽器內核互動,當然,爬蟲也可以用它,
具體做法如下:
- 引入pom依賴
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
-
配置對應瀏覽器的驅動
要使用selenium,需要下載瀏覽器的驅動,根據不同的瀏覽器要下載的驅動程式也不一樣,下載地址為:https://npm.taobao.org/mirrors/chromedriver/
我用的是谷歌瀏覽器,因此下載了對應版本的windows和linux驅動,


下載后需要配置進java環境變數里面,指定驅動的目錄:
System.getProperties().setProperty("webdriver.chrome.driver", "F:/download/chromedriver_win32_1/chromedriver.exe");
-
代碼實作:
Logger logger = LoggerFactory.getLogger(this.getClass()); public static void main(String[] args) { StockPriceSpider stockPriceSpider = new StockPriceSpider(); stockPriceSpider.seleniumProcess(); } private void seleniumProcess() { String uri = "http://quote.eastmoney.com/sh600036.html"; // 設定 chromedirver 的存放位置 System.getProperties().setProperty("webdriver.chrome.driver", "F:/download/chromedriver_win32_1/chromedriver.exe"); // 設定瀏覽器引數 ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--no-sandbox");//禁用沙箱 chromeOptions.addArguments("--disable-dev-shm-usage");//禁用開發者shm chromeOptions.addArguments("--headless"); //無頭瀏覽器,這樣不會打開瀏覽器視窗 WebDriver webDriver = new ChromeDriver(chromeOptions); webDriver.get(uri); WebElement webElements = webDriver.findElement(By.id("price9")); String stockPrice = webElements.getText(); logger.info("最新股價為 >>> {}", stockPrice); webDriver.close(); }執行結果:

爬取成功!
2.2反向決議法
反向決議法就是通過F12查找到 Ajax 異步獲取資料的鏈接,直接呼叫該鏈接得到json結果,然后直接決議json結果獲取想要的資料,
這個方法的關鍵就在于找到這個Ajax鏈接,這種方式我沒有去研究,感興趣的可以百度下,這里略,
3.結束語
以上即為如何通過selenium-java爬取異步加載的資料的方法,通過本方法,我寫了一個小工具:
持倉市值通知系統,他會每日根據自己的持倉配置,自動計算賬戶總市值,并郵件通知到指定郵箱,
用到的技術如下:
-
SpringBoot2:腳手架
-
Mybatis:ORM框架 以及對應的代碼自動生成工具
-
Jmail:發送郵件
-
Quartz:處理定時任務
-
Selenium-java:爬取最新股價
相關代碼已經上傳到我的碼云,感興趣可以看下,
本文來自博客園,作者:JAVA開發老菜鳥,轉載請注明原文鏈接:https://www.cnblogs.com/sam-uncle/p/15415526.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/320840.html
標籤:其他
上一篇:Python字典和集合
