爬山的蜗牛旅程:爬虫 Jsoup+(HtmlUnit或HttpClient)实现

学习的旅程,就像蜗牛爬山,一点点的往上爬,一点点的欣赏旅途的风景

Jsoup:解析和操作Html的技术(将html解析成document),通过操作document节点来解析元素属性和文本的技术(类似jQuery)

  • 1 Jsoup自身自持通过url请求静态html的
  • 2 Jsoup不支持解析执行js
  • 3 Jsoup有类似(jQuery操作document节点的)–此处网上很多教程

HttpClient:用于请求静态html的技术(获取请求返回的最原始的html)–不执行js

HtmlUnit:类似一个模拟浏览器的技术(通过模拟浏览器请求url,可触发请求返回的html所包含的js脚本)

具体实现

  • 第一步:pom.mxl配置
    	<!-- 爬虫 -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.10.2</version>
        </dependency>
        <!-- 爬虫 适用于包含动态js的html请求 -->
        <dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.27</version>
        </dependency>
        <!-- 爬虫 适用于纯静态html请求  -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
    
  • 基于HttpClient的爬虫例子
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;

/**
 * 基于org.apache.http.impl.client.HttpClients;方式去获取html数据(静态html,不执行js的纯静态html)
 * 1-为啥不用Jsoup请求html:因为功能,性能,效率都不如专业的org.apache.http.impl.client.HttpClients
 * 2-Jsoup是可以自己通过url去请求html(但是功能效率效果都不如上面的)
 * 3-Jsoup是解析操作html的工具
 * @author hxz
 */
public class HttpClient_Jsoup_Dome {
     
    /**
     *  通过HttpClient+Jsoup方式爬取数据
     * @param a
     */
    public static void main(String[] a)throws Exception{
     
        //通过HttpClient去请求html
        String Context=HttpClientHtml("http://www.baidu.com");
        //Jsoup解析html并获取图片路径
        doJsoup(Context,"http://www.baidu.com");
    }

    /**
     * HttpClient 请求静态html数据
     * @param URL
     * @return
     */
    public static String HttpClientHtml(String URL){
     
        //String URL="http://www.baidu.com";
        String Context="";

        //建立一个新的请求客户端
        CloseableHttpClient httpClient= HttpClients.createDefault();

        //使用HttpGet的方式请求网址
        HttpGet httpGet = new HttpGet(URL);

        //获取网址的返回结果
        CloseableHttpResponse response=null;
        try {
     
            response=httpClient.execute(httpGet);
        } catch (IOException e) {
     
            e.printStackTrace();
        }

        //获取返回结果中的实体
        HttpEntity entity = response.getEntity();

        //将返回的实体输出
        try {
     
            Context=EntityUtils.toString(entity, "utf-8");
            System.out.println(Context);
        } catch (IOException e) {
     
            e.printStackTrace();
        }
        return Context;
    }

    /**
     * 通过Jsoup解析html
     * @param html
     */
    public static void doJsoup(String html,String url) throws Exception{
     
        Document document = Jsoup.parse(html);
        //若HTML文档包含相对URLs路径,需要将这些相对路径转换成绝对路径的URLs
        document.setBaseUri(url);//指定base URI

        //获取所有的img元素
        Elements elements = document.select("img");
        int i=1;
        for (Element e : elements) {
     
            //获取每个src的绝对路径
            String src = e.absUrl("src");
            System.out.println(src);

            //获取图片
            //URL urlSource = new URL(src);
            //URLConnection urlConnection = urlSource.openConnection();

            //设置图片名字
            String imageName = src.substring(src.lastIndexOf("/") + 1,src.length());

            //控制台输出图片的src
            System.out.println(imageName);

            //通过URLConnection得到一个流,将图片写到流中,并且新建文件保存
            /*InputStream in = urlConnection.getInputStream();
            OutputStream out = new FileOutputStream(new File("E:\\IDEA\\imgs\\", imageName));
            byte[] buf = new byte[1024];
            int l = 0;
            while ((l = in.read(buf)) != -1) {
                out.write(buf, 0, l);
            }*/
        }
    }
}
  • 基于HtmlUnit的爬虫例子
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.util.List;

/**
 * 基于com.gargoylesoftware.htmlunit.WebClient;方式去获取html数据(包含js构建的动态html)
 * 1-为啥不用Jsoup请求html:因为功能,性能,效率都不如专业的com.gargoylesoftware.htmlunit.WebClient;【最重要的是不支持执行js】
 * 2-Jsoup是可以自己通过url去请求html(但是功能效率效果都不如上面的)
 * 3-Jsoup是解析操作html的工具
 * @author hxz
 */
public class HtmlUnit_Jsoup_Dome {
     
    /**
     * 通过Htmlunit+Jsoup方式爬取数据
     * @param
     */
   public static void main(String[] a){
     
       WebClient webClient = new WebClient(BrowserVersion.CHROME);//新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

       webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常, 这里选择不需要
       webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常, 这里选择不需要
       webClient.getOptions().setActiveXNative(false);
       webClient.getOptions().setCssEnabled(false);//是否启用CSS, 因为不需要展现页面, 所以不需要启用
       webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS
       webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,设置支持AJAX

       HtmlPage page = null;
       try {
     
           page = webClient.getPage("http://ent.sina.com.cn/film/");//尝试加载上面图片例子给出的网页
       } catch (Exception e) {
     
           e.printStackTrace();
       }finally {
     
           webClient.close();
       }

       webClient.waitForBackgroundJavaScript(30000);//异步JS执行需要耗时,所以这里线程要阻塞30秒,等待异步JS执行结束

       String pageXml = page.asXml();//直接将加载完成的页面转换成xml格式的字符串

       //TODO 下面的代码就是对字符串的操作了,常规的爬虫操作,用到了比较好用的Jsoup库

       Document document = Jsoup.parse(pageXml);//获取html文档
       List<Element> infoListEle = document.getElementById("feedCardContent").getElementsByAttributeValue("class", "feed-card-item");//获取元素节点等
       infoListEle.forEach(element -> {
     
           System.out.println(element.getElementsByTag("h2").first().getElementsByTag("a").text());
           System.out.println(element.getElementsByTag("h2").first().getElementsByTag("a").attr("href"));
       });
   }
}

你可能感兴趣的:(爬虫,Jsoup,爬虫,HtmlUnit,HttpClient)