使用Jsoup编写网络爬虫

以爬取Stack Overflow的搜索结果为例,使用Jsoup库编写Java网络爬虫

Jsoup是一个非常好用并且开源的Java爬虫(用来发送请求和解析Html的库),本篇笔记将会介绍如何使用Jsoup编写一个简单的网络爬虫,用来获取Stack Overflow的搜索结果

Jsoup官网有非常棒的文档,建议有能力的可以直接参考;

下面开始编写一个自己的Demo

  1. 首先创建一个Maven工程项目,并在pom.xml文件中导入jsoup包引用

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.2</version>
    </dependency>

  2. 创建一个java文件,命名为JsoupTest.java 引入需要的相应的引用

    1
    2
    3
    4
    5
    import org.jsoup.Jsoup;
    import org.jsoup.nodes.Document;
    import org.jsoup.nodes.Element;
    import org.jsoup.select.Elements;
    import java.io.IOException;

  3. 进入Stack Overflow首页,以IOException为例搜索一下,然后打开调试工具查看网页的结构,我们需要获取每个问题、问题的摘要以及问题的链接。

    stackOverflow

    选取我们需要的结果区域,可以看到我们要的元素在一个类型为question-summarydiv下一个类型为summarydiv下,其中:

    class="result-link"里面存着问题以及问题的链接;

    class="excerpt"里面存着问题的摘要;

    class="tags"里面存着问题的标签;

    class="started"里面存着提问日期

  4. 知道结构以后就可以开始编写爬虫了

    首先定义URL,Stackoverflow使用GET请求的方式来进行搜索,所以创建两个串

    1
    2
    static String url = "https://stackoverflow.com/search?q=";
    static String query = "IOException";

    第二个query串就是要搜索的内容,前面是查询url的前缀

    然后使用Jsoup发送请求,把query直接接在url后面就行

    1
    Document doc = Jsoup.connect(url+query).get();

    doc为收到的response,也就是整个页面,这时候就可以使用Jsoup的解析功能来提取我们需要的内容了:

    提取question-summary类下的summary类(CSS语法)

    1
    Elements elements = doc.select(".question-summary .summary");

    这样将得到一个Html元素的队列,然后迭代地进行内容的提取

    1
    2
    3
    4
    5
    6
    7
    for(Element e : elements){
    Elements title = e.select(".result-link h3 a");
    System.out.println("title: " + title.get(0).attr("title"));
    System.out.println("url: " + title.get(0).absUrl("href"));
    Elements excerpt = e.select(".excerpt");
    System.out.println("Excerpt: " + excerpt.text() + "\n");
    }

    同样也是采用CSS语法,attr()方法会获取元素里的某个属性值(Attribute),由于很多页面内的链接都是相对路径,absurl()会获取href属性中的url后,自动形成我们需要的绝对路径,text()将会获取元素中的文本元素(不包含标签),html()则是获得该元素下的所有内容;

  5. 然后查看显示结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    title: HttpClient request throws IOException
    url: https://stackoverflow.com/questions/13141434/httpclient-request-throws-ioexception
    Excerpt: The following code throws a IOException with the message: "The specified registry key does not exist." HttpClient client = new HttpClient(); Uri uri = new Uri("http://www.google.com …

    title: How to avoid Java code in JSP files?
    url: https://stackoverflow.com/questions/3177733/how-to-avoid-java-code-in-jsp-files/3180202#3180202
    Excerpt: , IOException { if (((HttpServletRequest) request).getSession().getAttribute("user") == null) { ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page … ServletException, IOException { try { List<Product> products = productService.list(); // Obtain all products. request.setAttribute("products", products); // Store products in …

    title: Understanding Java IOException
    url: https://stackoverflow.com/questions/5819121/understanding-java-ioexception
    Excerpt: I need some help with understanding the IOException. I've reviewed a lot of information on the internet, and looked at the technical specifications at Oracle's Java website. Am I correct in my … understanding of the IOException class and all of it's sub-classes, that there are no associated "error messages" or "return code" values? So if one wanted to issue some message and/or return code value …
    ...

完成我们要的提取

完整的代码