• Java 实现 HttpClients+jsoup,Jsoup,htmlunit,Headless Chrome 爬虫抓取数据


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

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

  • 相关阅读:
    二分查找
    Linux下查找目录中所有文件中含有某个字符串,并且只打印出文件名
    编码规范
    Cookie和Session的选择,以及如何解决分布式系统下各个服务器之间Session不统一的问题
    Mac VMware Fusion 11.5 虚拟机带密钥
    快速排序
    python装饰器
    商品详情页
    hadoop跑wordcount报expected org.apache.hadoop.io.Text, received org.apache.hadoop.io.LongWritable
    CentOS7设置共享文件夹不显示问题
  • 原文地址:https://www.cnblogs.com/sqy123/p/8986692.html
Copyright © 2020-2023  润新知