最近整理一下手头上搞过的一些爬虫,有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         }

 

----------------------------------------------------若有不正之处,请谅解和批评指正,不胜感激!!!!!