1.HtmlUnit是一個用java編寫的無界面瀏覽器,建模html文檔,通過API調用頁面,填充表單,點擊鏈接等等。如同正常瀏覽器一樣操作。典型應用於測試以及從網頁抓取信息。並且HtmlUnit擁有HttpClient和soup兩者的功能,但速度比較慢,但如果取消它的解析css和js的功能,速度也會提上去,默認開啟。
2.這里選用HtmlUnit來爬取數據主要是為了獲取他的js和css.
3.主要代碼如下
package com.los; import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.html.DomElement; import com.gargoylesoftware.htmlunit.html.DomNodeList; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.los.util.DownlandPic; import java.io.IOException; import java.util.regex.Pattern; public class HtmlUnitTest { public static void main(String[] args) throws IOException { DownlandPic dd = new DownlandPic(); WebClient webClient = new WebClient();//實例化web客戶端 //http://www.bdqn.cn/ https://www.baidu.com/?tn=78000241_22_hao_pg String url = "http://www.bdqn.cn/"; HtmlPage page = webClient.getPage(url); webClient.waitForBackgroundJavaScript(10000); //等侍js腳本執行完成 System.out.println(page.asXml()); DomNodeList<DomElement> img = page.getElementsByTagName("script"); for (int i=0;i<img.size();i++){ DomElement domElement = img.get(i); System.out.println("獲取的內容"+domElement); } //對其中的圖片進行操作 operPic(page); webClient.close();//關閉窗口,釋放內存 } /** * 將其中的圖片下載,並改變將爬取后的頁面中的圖片地址 * 將地址改為本地下載后的地址 * @param page */ public static void operPic(HtmlPage page){ DomNodeList<DomElement> img = page.getElementsByTagName("img"); for(int i=0;i<img.size();i++){ String content = img.get(i).toString(); String flag = ".*data-original.*"; //使用正則表達式匹配一個img中是否含有 data-original,去除背景圖片的干擾。 boolean matches = Pattern.matches(flag, content); System.out.println("匹配結果-------->"+matches); //匹配實例 <img class="lazy" data-original="/img/newImg/qn_pro4.jpg"...> if(matches){ //獲取到 data-original 里的值 String substring = content.substring(DownlandPic.getCharacterPosition3(content), DownlandPic.getCharacterPosition4(content)); System.out.println("截取的內容:"+substring); //將下載的圖片名稱定為截取的名字,爬取后的頁面和圖片在同一路徑 //調用下載圖片方法,獲取到的地址為相對路徑,在這將地址補充完整 String baseUrl = "http://www.bdqn.cn"; DownlandPic.downloadPicture(baseUrl+substring,"L:\\Spider\\"+substring); } System.out.println("圖片路徑"+content); } } }
圖片下載和正則匹配
package com.los.util; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; public class DownlandPic { public static void downloadPicture(String urlList,String path){ try { URL url = new URL(urlList); DataInputStream dataInputStream = new DataInputStream(url.openStream()); FileOutputStream fileOutputStream = new FileOutputStream(new File(path)); ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = dataInputStream.read(buffer)) > 0) { output.write(buffer, 0, length); } fileOutputStream.write(output.toByteArray()); dataInputStream.close(); fileOutputStream.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static int getCharacterPosition3(String string){ //這里是獲取"\""符號的位置 Matcher slashMatcher = Pattern.compile("\"").matcher(string); int mIdx = 0; while(slashMatcher.find()) { mIdx++; //當"/"符號第三次出現的位置 if(mIdx == 2){ break; } } return slashMatcher.start(); } public static int getCharacterPosition4(String string){ //這里是獲取"\""符號的位置 Matcher slashMatcher = Pattern.compile("\"").matcher(string); int mIdx = 0; while(slashMatcher.find()) { mIdx++; //當"/"符號第三次出現的位置 if(mIdx == 3){ break; } } return slashMatcher.start(); } public static void main(String[] args) { String content = "<img class=\"lazy\" data-original=\"/img/newImg/news_img2.jpg\" src=\"/img/newImg/news2.jpg\" style=\"display: block;\"/>"; System.out.println(getCharacterPosition3(content)); System.out.println(getCharacterPosition4(content)); String substring = content.substring(getCharacterPosition3(content), getCharacterPosition4(content)); System.out.println(substring); } }
3.因為這里的網頁中圖片地址為相對路徑,所以在進行下載的時候到頁面找了它的絕對路徑在下載地址中進行了拼接。將下載的路徑和爬取后要存儲在本地的頁面中的圖片標簽中的地址要對應,否則找不到。
3.在匹配 " 時之所以寫2和3是根據這里爬取的數據來寫的
4.相對於其他爬取網頁的寫法,這個可能比較簡單,但能比較容易的體現出效果,出現錯誤還請多多指教。至於頁面就不展示了,涉及隱私。
5.關於HtmlUnit的學習可以參考:地址