前言

事先写过一篇用jsoup爬取csdn博客的稿子JAVA爬虫挖取CSDN博客小说,当时博主还在上一家集团见习,由于店铺办公室互连网需求代理才能访问外网,那一篇的代码逻辑与代理密切相关,可能有些不熟悉jsoup怎么使用的仇人看了会感到越看越繁杂,且立刻以为爬取所有文章须求用到分页,可能会误导读者。所以明天重新整理这几个篇博客的思路,在未曾代理的网络的环境下已毕代码功效,如果您的也是处在代理才能访问外网的互联网,那么参考本文最终一段的化解方案。

思路和步子

抑或以《第一行代码–安卓》的小编为例,将她在csdn揭橥的博客音讯都挖取出来,因为郭神是本身在大学时期比较崇拜的目标之一。郭神的博客地址为郭霖博客
jQuery 1

在出手实验此前,假诺你早就基本通晓了之类的技艺:JAVA基础编程,简单的正则表达式,JS或者jQuery的编程能力,其它还学过http协议的一部分学问。借使你还未控制正则表明式,可以去自己的JAVA正则表达式详解博客看看,如若您还从未了解jQuery的基础知识,可以去自己的jQuery实战专栏下手实验一番。假如上诉技能你都控制了,那么就只差一个jsoup了,那个哥们是干嘛使的吗?用一句话来讲述:那哥俩能使Java程序像jQuery那样的语法来操作html的Dom节点元素,jsoup也有像jQuery一样的选拔器功用,比如getElementById,getElemementsByClass等语法与JavaScript像极了,其它jsoup还有select拔取器功用。所以,这里只要稍微控制jsoup语法就足以像JS操作Dom一样的用Java来拍卖请求到的html网页。jsoup的国语官方教程地址http://www.open-open.com/jsoup/

工欲善其事必先利其器。开首从前,你应有有必然的工具,比如一款熟悉的ide,用来调节和查看变量。一个web调试工具,如火狐的firebug之类的。由此可见,就是有一个java
web程序员平常支出和调剂使用的工具就大多了。

率先步:新建一个Java
Se项目。这么些项目只如若一个Maven项目,那么须求充足如下的依靠配置:

<dependency>
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.10.2</version>
</dependency>

万一那一个类型不是Maven项目,那么您须要下载jsoup-1.10.2.jar包,然后在你的品种右键新建一个lib目录,把下载的jar包放进去,并把jar包添加到classpath。
jQuery 2

其次步:分析代码编写思路:先创立一个Conection链接,这些链接包罗向CSDN服务器发起呼吁的url地址,userAgent参数,timeOut参数已经Http请求类型等。接着向服务器发送get请求Document
doc =
conn.get();注意:很多网络原因促成这一步出现非凡,比如timeOut时间设置太短也会报错,那里自己设置为5000微秒。即使这一步你的次第尚未报错,表明已经得到了请求的html文档。然后大家得以将html的body标签里面的内容赋值给遍历Element数据类型的实例body。处理body标签的始末jsoup正式登场,除了jsoup还会混杂不难的正则内容。

用firebug可以看到。首页与博客小说相关的内容在这些div
class=”list_item_new”标签上面,而以此div下边包罗3个div,分别是:div
id=”article_toplist” class=”list”表示置顶的作品,div id=”article_list”
class=”list”博文列表所在的div,div id=”papelist”
class=”pagelist”底下分页音信所在的div。抛开置顶那几个div,我们只关心小说列表的div和分页音信div。借使您仔细的解析,那么会发觉我们关怀的每篇小说而每篇作品的竹签如下div:`

jQuery 3
每篇小说占据的div,完整的html元素如下:

<div class="list_item article_item">
        <div class="article_title">   



    <h1>
        <a href="/guolin_blog/article/details/51336415">
        Android提醒微技巧,你真的了解Dialog、Toast和Snackbar吗?            
        </a>
    </h1>
</div>

        <div class="article_description">
Dialog和Toast所有人肯定都不会陌生的,这个我们平时用的实在是太多了。而Snackbar是Design Support库中提供的新控件,有些朋友可能已经用过了,有些朋友可能还没去了解。但是你真的知道什么时候应该使用Dialog,什么时候应该使用Toast,什么时候应该使用Snackbar吗?本篇文章中我们就来学习一下这三者使用的时机,另外还会介绍一些额外的技巧...        </div>
            <div class="article_manage">
             2016-07-26 07:55


        <a href="/guolin_blog/article/details/51336415" title="阅读次数">阅读</a>(7458)
        <a href="/guolin_blog/article/details/51336415#comments" title="评论次数" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(45)

    </div>

        <div class="clear"></div>
    </div>

有心人分析一下,那一个div中涵盖了作品的简介,阅读次数,连接地址等等,不言而喻,那么些div才是重点要获取的数码都在那吗。
jQuery 4

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

/**
 * java爬取csdn博客的简单的案例,如果你只爬取某个博主的首页文章,那么参考本程序员
 * 如果你想爬取某位博主的所有文章,请参考Main.java
 * @author shizongger
 * @date 2017/02/09
 */
public class Main1 {

    //需要进行爬取得博客首页
//  private static final String URL = "http://blog.csdn.net/guolin_blog";
    private static final String URL = "http://blog.csdn.net/sinyu890807/article/list/2";

    public static void main(String[] args) throws IOException {

        //获取url地址的http链接Connection
        Connection conn = Jsoup.connect(URL)    //博客首页的url地址
                .userAgent("Mozilla/5.0 (Windows NT 6.1; rv:47.0) Gecko/20100101 Firefox/47.0") //http请求的浏览器设置
                .timeout(5000)   //http连接时长
                .method(Connection.Method.GET);  //请求类型是get请求,http请求还是post,delete等方式
        //获取页面的html文档
        Document doc = conn.get();
        Element body = doc.body();

        //将爬取出来的文章封装到Artcle中,并放到ArrayList里面去
        List<Article> resultList = new ArrayList<Article>();

        Element articleListDiv = body.getElementById("article_list");
        Elements articleList = articleListDiv.getElementsByClass("list_item");
        for(Element article : articleList){
            Article articleEntity = new Article();
            Element linkNode = (article.select("div h1 a")).get(0);         
            Element desptionNode = (article.getElementsByClass("article_description")).get(0);
            Element articleManageNode = (article.getElementsByClass("article_manage")).get(0);

            articleEntity.setAddress(linkNode.attr("href"));
            articleEntity.setTitle(linkNode.text());
            articleEntity.setDesption(desptionNode.text());
            articleEntity.setTime(articleManageNode.select("span:eq(0").text());

            resultList.add(articleEntity);
        }

        //遍历输出ArrayList里面的爬取到的文章
        System.out.println("文章总数:" + resultList.size());
        for(Article article : resultList) {
            System.out.println("文章绝对路劲地址:http://blog.csdn.net" + article.getAddress());
        }
    }

}

当今可以将近日页数的小说挖掘出来了,但是郭神的技巧小说频频一页啊,还要更进一步分页挖掘。以前我是想Java的分页思路是怎么写的,大家可以逆着它的分页思路来。可是现在感到与它怎么分页无关,可是借使你通晓Java分页那么更好的知道接下去怎么办。

要想爬取它的持有小说,可以对她的博客每一个页面分别进行呼吁。
首页地址能够是:

http://blog.csdn.net/guolin_blog

也可以是:

http://blog.csdn.net/guolin_blog/article/list/1

那么第二页未来的url地址如下:

http://blog.csdn.net/guolin_blog/article/list/index

index表示请求的页数。

前天的天职就是来抓取总页数了。来来来,我们用firebug看一看。
jQuery 5

<div id="papelist" class="pagelist">
 100条  共7页<a href="/sinyu890807/article/list/1">首页</a> <a href="/sinyu890807/article/list/3">上一页</a> <a href="/sinyu890807/article/list/1">1</a> <a href="/sinyu890807/article/list/2">2</a> <a href="/sinyu890807/article/list/3">3</a> <strong>4</strong> <a href="/sinyu890807/article/list/5">5</a> <a href="/sinyu890807/article/list/6">...</a> <a href="/sinyu890807/article/list/5">下一页</a> <a href="/sinyu890807/article/list/7">尾页</a> 
    </div>

可以看到总页数位居上诉div下的首先个span标签,幸运的是其一div有一个无比的id号,而以此span与div的关联是父节点与子节点的关联,获取图中红圈内字符串的代码是”body.getElementById(“papelist”).select(“span:eq(0)”).text();”。而span标签里面的内容”
100条
共7页”是汉字,空格和数字混合组成,这时候正则表明式闪亮登场。为了挑选”共x页”里面的x的值,正则的语法关键代码是:String
regex = “.+共(\d+)页”;

迄今截止,就可以将郭霖的csdn技术博客都得以博得了。此时您只需求将得到的新闻都打包好,在急需的时候调用就行了。
完全代码如下:
Article.java

/**
 * 文章的JavaBean.
 * date:2017-02-09
 */
public class Article {

    /**
     * 文章链接的相对地址
     */
    private String address;

    /**
     * 文章标题
     */
    private String title;

    /**
     * 文章简介
     */
    private String desption;

    /**
     * 文章发表时间
     */
    private String time;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesption() {
        return desption;
    }

    public void setDesption(String desption) {
        this.desption = desption;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

Main.java

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.*;
import org.jsoup.nodes.*;
import org.jsoup.select.*;

import com.shizongger.javaspider.Article;

/**
 * @author shizongger
 * @date 2017/02/09
 */
public class Main {

    private static final String URL = "http://blog.csdn.net/guolin_blog";

    public static void main(String[] args) throws IOException {
        Connection conn = Jsoup.connect(URL)
                .userAgent("Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0")
                .timeout(5000)
                .method(Connection.Method.GET);
        Document doc = conn.get();
        Element body = doc.body();

        //获取总页数
        String totalPageStr = body.getElementById("papelist").select("span:eq(0)").text();
        String regex = ".+共(\\d+)页";
        totalPageStr = totalPageStr.replaceAll(regex, "$1");
        int totalPage = Integer.parseInt(totalPageStr);
        int pageNow = 1;

        List<Article> articleList = new ArrayList<Article>();
        for(pageNow = 1; pageNow <= totalPage; pageNow++){
            articleList.addAll(getArtitcleByPage(pageNow));
        }

        //遍历输出博主所有的文章
        for(Article article : articleList) {
            System.out.println("文章标题:" + article.getTitle());
            System.out.println("文章绝对路劲地址:http://blog.csdn.net" + article.getAddress());
            System.out.println("文章简介:" + article.getDesption());
            System.out.println("发表时间:" + article.getTime());
        }
    }

    public static List<Article> getArtitcleByPage(int pageNow) throws IOException{

        Connection conn = Jsoup.connect(URL + "/article/list/" + pageNow)
                .userAgent("Mozilla/5.0 (Windows NT 6.1; rv:47.0) Gecko/20100101 Firefox/47.")
                .timeout(5000)
                .method(Connection.Method.GET);
        Document doc = conn.get();
        Element body = doc.body();
        List<Article> resultList = new ArrayList<Article>();

        Element articleListDiv = body.getElementById("article_list");
        Elements articleList = articleListDiv.getElementsByClass("list_item");
        for(Element article : articleList){
            Article articleEntity = new Article();
            Element linkNode = (article.select("div h1 a")).get(0);         
            Element desptionNode = (article.getElementsByClass("article_description")).get(0);
            Element articleManageNode = (article.getElementsByClass("article_manage")).get(0);

            articleEntity.setAddress(linkNode.attr("href"));
            articleEntity.setTitle(linkNode.text());
            articleEntity.setDesption(desptionNode.text());
            articleEntity.setTime(articleManageNode.select("span:eq(0").text());

            resultList.add(articleEntity);
        }
        return resultList;
    }
}

三个注意之处

  1. Conection的timeOut不宜过短。要是把timeOut设置为20阿秒,则会报错。
    Exception in thread “main” java.net.SocketTimeoutException: connect
    timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at
    java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at
    java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at
    java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
    at sun.net.www.http.HttpClient.

2.当您处在内网时,必要代理才能发送http请求,在Jsoup.connect(URL)从前,你不可以不安装代理。

        System.setProperty("http.maxRedirects", "50");
        System.getProperties().setProperty("proxySet", "true");
        String ip = "代理服务器地址";
        System.getProperties().setProperty("http.proxyHost", ip);
        System.getProperties().setProperty("http.proxyPort", "代理的端口");

本文可运行案例托管在免积分下载地址,本文目标用于技术沟通,望与海内外Coder共勉!

相关文章

网站地图xml地图