最近整理一下手頭上搞過的一些爬蟲,有HttpClients+jsoup,Jsoup,htmlunit,HeadlessChrome
一、HttpClients+jsoup,這是第一代比較low,很快就被第二代代替了!
二、Jsoup
需要的jar包:
1 <dependency> 2 <groupId>org.jsoup</groupId> 3 <artifactId>jsoup</artifactId> 4 <version>1.10.3</version> 5 </dependency>
代碼如下:
1 // 請求超時時間,30秒 2 public static final int TIME_OUT = 30*1000; 3 // 模擬瀏覽器請求頭信息 4 public static Map<String,String> headers = new HashMap<String,String>(); 5 static{ 6 headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0"); 7 headers.put("Accept", "text/html"); 8 headers.put("Accept-Language", "zh-CN,zh"); 9 } 10 11 //根據url獲取html文檔 12 protected Document getDoc(String url) throws IOException{ 13 if(logger.isDebugEnabled()) 14 logger.debug(url); 15 //新建一個連接 16 Connection conn = Jsoup.connect(url).timeout(TIME_OUT); 17 conn = conn.headers(headers); 18 conn = conn.proxy(Proxy.NO_PROXY); 19 Document doc = conn.get(); 20 21 if(logger.isTraceEnabled()){ 22 logger.trace("["+url+"]\n"+doc); 23 } 24 return doc; 25 }
1 public static final String CHINAZ_ICP_URL = "http://icp.chinaz.com/?type=host&s=%s"; 2 public List<String> doHandler(String domain) { 3 List<String> results = new ArrayList<String>(); 4 String url = String.format(CHINAZ_ICP_URL, domain); 5 Document doc; 6 try { 7 doc = this.getDoc(url); 8 // 獲取當前頁ICP信息所在標簽 9 Elements eles = doc.select("ul.IcpMain01>li:lt(7)>p"); 10 11 if(null == eles || eles.isEmpty()){ 12 return results; 13 } 14 //獲取ICP信息 15 for (Element element : eles) { 16 //當前元素為認證信息時,跳過 17 if("safe".equals(element.attr("id"))){ 18 continue; 19 } 20 Node firstNode = element.childNode(0); 21 if(firstNode.childNodeSize() > 0){ 22 results.add(element.child(0).text()); 23 }else{ 24 results.add(((TextNode)firstNode).text()); 25 } 26 } 27 } catch (IOException e) { 28 logger.error("get Chinaz ICP message error :",e); 29 } 30 doc = null; 31 return results; 32 }
參考Jsoup的文檔:鏈接http://www.open-open.com/jsoup/
Jsoup不支持xpath解析,這個很蛋疼,但是有人去搞個一個支持xpath的東西---JsoupXpath,鏈接https://www.cnblogs.com/wanghaomiao/p/4899355.html,有興趣的網友可以自己嘗試一下!
三、htmlunit
支持Xpath解析,能夠模擬瀏覽器動作,比如點擊下一頁,加載更多等等功能。文檔鏈接:http://htmlunit.sourceforge.net/
需要的jar包
1 <dependency> 2 <groupId>net.sourceforge.htmlunit</groupId> 3 <artifactId>htmlunit</artifactId> 4 <version>2.18</version> 5 </dependency>
代碼如下:
1 import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; 2 import com.gargoylesoftware.htmlunit.TopLevelWindow; 3 import com.gargoylesoftware.htmlunit.WebClient; 4 import com.gargoylesoftware.htmlunit.html.HtmlPage; 5 import com.gargoylesoftware.htmlunit.html.HtmlTableRow; 6 7 import java.io.IOException; 8 import java.util.ArrayList; 9 import java.util.List; 10 11 12 public class UrlTest { 13 14 public static void main(String[] args) { 15 BaseCollector baseCollector = new BaseCollector(); 16 WebClient webClient = baseCollector.getWebClient(); 17 String url="http://htmlunit.sourceforge.net/"; 18 HtmlPage homePage= null; 19 try { 20 homePage = webClient.getPage(url); 21 if (homePage != null && homePage instanceof HtmlPage) { 22 homePage.getEnclosingWindow().setName("IpHomePage"); 23 System.out.println("打開 IPHomePage "); 24 System.out.println("內容是: "+homePage.getBody().getTextContent()); 25 26 List<HtmlTableRow> htmlTableRows = (List<HtmlTableRow>) homePage.getByXPath("/html/body/pre"); 27 if (htmlTableRows != null && htmlTableRows.size() > 0) { 28 for (int i = 0; i < htmlTableRows.size(); i++) { 29 HtmlTableRow htmlTableRow = htmlTableRows.get(i); 30 //日期 31 String firstTime = htmlTableRow.getCell(0).getTextContent().trim(); 32 System.out.println(firstTime); 33 } 34 35 } 36 closeWindowByName(webClient, "IPHomePage"); 37 System.out.println("關閉 IPHomePage "); 38 } 39 webClient.close(); 40 41 } catch (IOException e) { 42 System.out.println(e.getMessage()+" ===="+e); 43 }catch (FailingHttpStatusCodeException e){ 44 System.out.println(e.getMessage()+" ===="+e); 45 } 46 System.out.println("內容是: "+homePage.getBody().getTextContent()); 47 } 48 49 public static void closeWindowByName(WebClient webClient, String name){ 50 List<TopLevelWindow> list = webClient.getTopLevelWindows(); 51 List windowNames = new ArrayList(); 52 for (int j = 0; j < list.size(); j++) { 53 if(list.get(j).getName().equals(name)){ 54 list.get(j).close(); 55 } 56 windowNames.add(list.get(j).getName()); 57 } 58 System.out.println("當前窗口 : {}"+list.toString()); 59 } 60 } 61 62
四、HeadlessChrome
1,Headless Chrome 與PhantomJS對比
在 Chrome 未提供原生 Headless 模式前,Web 開發者可以使用 PhantomJS 等第三方 Headless 瀏覽器。現在官方准備提供 Headless 了,PhantomJS 維護者 Vitaly Slobodin 隨即在郵件列表上宣布辭職。另一個流行瀏覽器 Firefox 也准備提供 Headless 模式。
2,什么是Headless Chrome
Headless Chrome 是 Chrome 瀏覽器的無界面形態,可以在不打開瀏覽器的前提下,使用所有 Chrome 支持的特性運行你的程序。相比於現代瀏覽器,Headless Chrome 更加方便測試 web 應用,獲得網站的截圖,做爬蟲抓取信息等。
3,環境配置
首先需要下載chrome-driver,不同版本的Chrome對應不同的Chrome-driver,大家可以通過這鏈接下載對應的Chrome-driver http://npm.taobao.org/mirrors/chromedriver/
支持各種elements的獲取,List<WebElement> elements = driver.findElements(By.xpath("//*[@id=\"body\"]/ul[2]/li"));
可以模擬瀏覽器的各種動作,driver.findElement(By.linkText("下一頁")).click();
使用Python來搞HeadlessChrome更方便簡單,簡直爽翻天。。。。。鏈接:https://blog.csdn.net/u010986776/article/details/79266448
大家可以參考一下
需要的jar包:
1 <dependency> 2 <groupId>org.seleniumhq.selenium</groupId> 3 <artifactId>selenium-chrome-driver</artifactId> 4 <version>3.11.0</version> 5 </dependency>
代碼如下:
1 import org.jsoup.Jsoup; 2 import org.jsoup.nodes.Document; 3 import org.openqa.selenium.By; 4 import org.openqa.selenium.WebDriver; 5 import org.openqa.selenium.WebElement; 6 import org.openqa.selenium.chrome.ChromeDriver; 7 import org.openqa.selenium.chrome.ChromeOptions; 8 9 import java.util.List; 10 import java.util.concurrent.TimeUnit; 11 12 /** 13 * Created by sqy on 2018/5/2. 14 */ 15 public class HeadlessChromeTest { 16 17 public static void main(String args[]) { 18 19 20 21 //G:\chromedriver 22 System.setProperty("webdriver.chrome.driver","G:\\chromedriver\\chromedriver.exe"); 23 ChromeOptions chromeOptions = new ChromeOptions(); 24 // 設置為 headless 模式 (必須) 25 chromeOptions.addArguments("--headless"); 26 // 設置瀏覽器窗口打開大小 (非必須) 27 chromeOptions.addArguments("--window-size=1920,1080"); 28 WebDriver driver = new ChromeDriver(chromeOptions); 29 driver.get("https://lvyou.baidu.com/scene/s-feb/"); 30 31 System.out.println("url: "+driver.getCurrentUrl()); 32 33 for(int i=0;i<12;i++){ 34 try { 35 /** 36 * WebDriver自帶了一個智能等待的方法。 37 dr.manage().timeouts().implicitlyWait(arg0, arg1); 38 Arg0:等待的時間長度,int 類型 ; 39 Arg1:等待時間的單位 TimeUnit.SECONDS 一般用秒作為單位。 40 */ 41 driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); 42 } catch (Exception e) { 43 e.printStackTrace(); 44 } 45 //點擊按鈕 46 driver.findElement(By.linkText("下一頁")).click(); 47 List<WebElement> elements = driver.findElements(By.xpath("//*[@id=\"body\"]/ul[2]/li")); 48 for (WebElement el:elements) { 49 System.out.println(el.getText()); 50 } 51 System.out.println("url: "+driver.getCurrentUrl()); 52 } 53 54 /** 55 * dr.quit()和dr.close()都可以退出瀏覽器,簡單的說一下兩者的區別:第一個close, 56 * 如果打開了多個頁面是關不干凈的,它只關閉當前的一個頁面。第二個quit, 57 * 是退出了所有Webdriver所有的窗口,退的非常干凈,所以推薦使用quit最為一個case退出的方法。 58 */ 59 driver.quit(); 60 61 62 } 63 }
HeadlessChrome的webdriver是在selenium里面的所以很多功能可以通過查詢java selenium 功能來查找自己想要實現的功能!
例如截屏功能
1 //截圖 2 File scrFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); 3 try { 4 String savePath = "H:\\bbb\\screenshot.png"; 5 //復制內容到指定文件中 6 FileUtils.copyFile(scrFile, new File(savePath)); 7 } catch (Exception e) { 8 e.printStackTrace(); 9 }
----------------------------------------------------若有不正之處,請諒解和批評指正,不勝感激!!!!!