1. 程式人生 > >jsoup+htmlUnit可以實現抓取執行過js的html頁面

jsoup+htmlUnit可以實現抓取執行過js的html頁面

1:背景

  本來想用jsoup去抓取一個頁面但是抓取的資料總是不全,然後發現有的資料是頁面執行過js之後渲染到頁面上的,也就是說只有執行過js之後資料頁面上才會顯示資料,但是jsoup並不能實現執行頁面的js。

2:解決

  搜尋後發現htmlunit網路工具可以實現執行js,他是一個相當於一個沒有頁面的瀏覽器,解決方案就是先使用htmlUnit傳送網路請求,執行js獲取頁面然後利用jsoup再轉換為Document頁面物件,然後使用jsoup分析頁面讀取資料。

3:htmlUnit傳送請求

 1 public static Document getDocument() throws
IOException, InterruptedException{ 2 /*String url="https://www.marklines.com/cn/vehicle_sales/search_country/search/?searchID=587200"; 3 Connection connect = Jsoup.connect(url).userAgent("") 4 .header("Cookie", "PLAY_LANG=cn; _plh=b9289d0a863a8fc9c79fb938f15372f7731d13fb; PLATFORM_SESSION=39034d07000717c664134556ad39869771aabc04-_ldi=520275&_lsh=8cf91cdbcbbb255adff5cba6061f561b642f5157&csrfToken=209f20c8473bc0518413c226f898ff79cd69c3ff-1539926671235-b853a6a63c77dd8fcc364a58&_lpt=%2Fcn%2Fvehicle_sales%2Fsearch&_lsi=1646321; _ga=GA1.2.2146952143.1539926675; _gid=GA1.2.1032787565.1539926675; _plh_notime=8cf91cdbcbbb255adff5cba6061f561b642f5157")
5 .timeout(360000000); 6 Document document = connect.get();*/ 7 WebClient wc = new WebClient(BrowserVersion.CHROME); 8 //是否使用不安全的SSL 9 wc.getOptions().setUseInsecureSSL(true); 10 //啟用JS直譯器,預設為true 11 wc.getOptions().setJavaScriptEnabled(true
); 12 //禁用CSS 13 wc.getOptions().setCssEnabled(false); 14 //js執行錯誤時,是否丟擲異常 15 wc.getOptions().setThrowExceptionOnScriptError(false); 16 //狀態碼錯誤時,是否丟擲異常 17 wc.getOptions().setThrowExceptionOnFailingStatusCode(false); 18 //是否允許使用ActiveX 19 wc.getOptions().setActiveXNative(false); 20 //等待js時間 21 wc.waitForBackgroundJavaScript(600*1000); 22 //設定Ajax非同步處理控制器即啟用Ajax支援 23 wc.setAjaxController(new NicelyResynchronizingAjaxController()); 24 //設定超時時間 25 wc.getOptions().setTimeout(1000000); 26 //不跟蹤抓取 27 wc.getOptions().setDoNotTrackEnabled(false); 28 WebRequest request=new WebRequest(new URL("https://www.marklines.com/cn/vehicle_sales/search_country/search/?searchID=587200")); 29 request.setAdditionalHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0"); 30 request.setAdditionalHeader("Cookie","PLAY_LANG=cn; _plh=b9289d0a863a8fc9c79fb938f15372f7731d13fb; PLATFORM_SESSION=39034d07000717c664134556ad39869771aabc04-_ldi=520275&_lsh=8cf91cdbcbbb255adff5cba6061f561b642f5157&csrfToken=209f20c8473bc0518413c226f898ff79cd69c3ff-1539926671235-b853a6a63c77dd8fcc364a58&_lpt=%2Fcn%2Fvehicle_sales%2Fsearch&_lsi=1646321; _ga=GA1.2.2146952143.1539926675; _gid=GA1.2.1032787565.1539926675; _plh_notime=8cf91cdbcbbb255adff5cba6061f561b642f5157"); 31 try { 32 //模擬瀏覽器開啟一個目標網址 33 HtmlPage htmlPage = wc.getPage(request); 34 //為了獲取js執行的資料 執行緒開始沉睡等待 35 Thread.sleep(1000);//這個執行緒的等待 因為js載入需要時間的 36 //以xml形式獲取響應文字 37 String xml = htmlPage.asXml(); 38 //並轉為Document物件return 39 return Jsoup.parse(xml); 40 //System.out.println(xml.contains("結果.xls"));//false 41 } catch (FailingHttpStatusCodeException e) { 42 e.printStackTrace(); 43 } catch (MalformedURLException e) { 44 e.printStackTrace(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 return null; 49 }

4:返回的Document物件交給jsoup進行處理

  在這裡只做了一個簡單的輸出,查看了一下資料是否渲染全部。

 1 Document doc=getDocument();
 2         Element table=doc.select("table.table.table-bordered.aggregate_table").get(0);//獲取到表格
 3         Element tableContext=table.getElementsByTag("tbody").get(0);
 4         Elements contextTrs=tableContext.getElementsByTag("tr");
 5         System.out.println(contextTrs.size());
 6         
 7         
 8         String context=doc.toString();
 9         OutputStreamWriter pw = null;
10         pw = new OutputStreamWriter(new FileOutputStream("D:/test.txt"),"GBK");
11         pw.write(context);
12         pw.close();