jsoup爬虫技术及爬取微博数据实例

  最近实现了一个爬取微博数据的小程序,借此对爬虫技术 jsoup的使用,以及实际开发过程中的细节进行总结。

   jsoup的jar包下载地址:https://jsoup.org/download

  首先,对于网络爬虫的理解,它是一种能够自动下载网页、解析网页的程序。网络中的信息分散在数以亿计的网页中,而这些网页中的数据存储于数以百万计的服务器中。现实中的用户只需通过在浏览器中访问超链接便可以获取信息。爬虫便可以通过模拟浏览器的方式,将多个超链接对应的网页信息收集起来。而Jsoup要做的,就是帮我们完成这样一个程序。它是一个 Java 的开源HTML解析器,可直接解析某个URL地址,它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。它可以帮我们完成:

1. 从一个URL,文件或字符串中解析HTML 
2. 使用DOM或CSS选择器来查找、取出数据 
3. 对HTML元素、属性、文本进行操作 
4. 清除不受信任的HTML (来防止XSS攻击)

 jsoup 可以从包括字符串、URL 地址以及本地文件来加载 HTML 文档,并生成 Document 对象实例。下面贴出代码对几种方式进行解析:

// 从 URL中加载 HTML 文档
	String url = "https://s.weibo.com/";
	Document doc = Jsoup.connect(url).get();

	// 从字符串中输入 HTML 文档
	String html = "<html><head><title>MyPaper</title></head>" + "<body><p>这是一个页面</p></body></html>";
	Document doc = Jsoup.parse(html);

	// 从文件中加载 HTML 文档
	File input = new File("MyPage.html");try
	{
		Document doc3 = Jsoup.parse(input, "UTF-8", "https://s.weibo.com/");

	}catch(
	IOException e)
	{

		e.printStackTrace();
	}
    

而对于解析出来的Document对象,Element对象则提供了一系列类似于DOM的方法来查找元素,抽取并处理其中的元素:

//通过标签里的id,tag,className等进行查找:
    getElementById(String id)

    getElementsByTag(String tag)

    getElementsByClass(String className)

    getElementsByAttribute(String key) (and related methods)

    Element siblings: siblingElements(), firstElementSibling(), lastElementSibling(); nextElementSibling(), previousElementSibling()

    Graph: parent(), children(), child(int index)

    
    //定位后对所在标签和元素进行操作
    attr(String key) :获取属性
    attr(String key, String value) :设置属性
    attributes() :获取所有属性
    text() : 获取文本内容
    text(String value) : 设置文本内容
    html() : 获取元素内HTML
    html(String value) : 设置元素内的HTML内容
    outerHtml() : 获取元素外HTML内容
    data() : 获取数据内容

下面用一个爬取微博数据的实例进行讲解:

需求 :从数据源界面如下所示:http://www.weibo.com 爬取:

 微博(微博ID,微博昵称,微博内容,发布时间,发布平台,转发数,评论数,点赞数)

 

首先分析需要爬取的目标网页的url地址:

 

 

 

 

 

因此从url中进行加载的语句可写为:

				String word = "双一流";
				String url = "https://s.weibo.com/weibo?q=" + word + "&Refer=index&page=" + i;
				Document doc = Jsoup.connect(url).userAgent("ie7:mozilla/4.0 (compatible; msie 7.0b; windows nt 6.0)")// 模拟浏览器访问
						.timeout(3000)// 设置超时
						.get();

下面对网页进行分析,为下一步使用Element对象抽取处理元素做准备:

 

 

可以注意到每一个微博动态块位于一个 action-type=feed_list_item 的div块中,但每篇热门文章也位于action-type=feed_list_item 的div块中,这是我们需要进行过滤的,对于解析出来的Document对象,Element对象则提供了一系列类似于DOM的方法来查找元素,抽取并处理其中的元素,下面是选取的其中一个 动态块源代码 :

<!--card-wrap-->
<div class="card-wrap" action-type="feed_list_item" mid="4295851763028004" >
        <div class="card-top">
        <div class="card-top">
                                                                <h4 class="title"><i class="icon-title icon-star"></i><a href="/weibo?q=%E5%8F%8C%E4%B8%80%E6%B5%81&xsort=hot&Refer=hotmore" target="_blank" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,click:more">热门</a></h4>
                    </div>
    </div>
        <div class="card">
        <div class="card-feed">
            <div class="avator">
                <a href="//weibo.com/1734530730?refer_flag=1001030103_" target="_blank" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:user_pic"><img src="//tvax2.sinaimg.cn/crop.0.0.996.996.50/6762d6aaly8fuuyo3xbt5j20ro0ro74w.jpg" /></a>
            </div>
            <!--微博内容-->
            <div class="content" node-type="like">
                <div class="info">
                    <div class="menu s-fr">
                        <a href="javascript:void(0);" action-type="fl_menu"><i class="wbicon">c</i></a>
                        <ul node-type="fl_menu_right" style="display:none;">
                            <li><a href="javascript:void(0);" onclick="javascript:window.open('//service.account.weibo.com/reportspam?rid=4295851763028004&amp;type=1&amp;from=10501&amp;url=&amp;bottomnav=1&amp;wvr=6', 'newwindow', 'height=700, width=550, toolbar =yes, menubar=no, scrollbars=yes, resizable=yes, location=no, status=no');">举报</a></li>
                                                    </ul>
                    </div>
                    <div>
                        <a href="//weibo.com/1734530730?refer_flag=1001030103_" class="name" target="_blank" nick-name="大河报" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:user_name">大河报</a>
                        <a href="//verified.weibo.com/verify" target="_blank"  title="微博官方认证"><i class="icon-vip icon-vip-b"></i></a>
                        <!--广告微博加关注按钮 -->
                                            </div>
                </div>
                <p class="txt" node-type="feed_list_content" nick-name="大河报">
                    【大手笔!河南省财政厅2018年度安排“<em class="s-color-red">双</em><em class="s-color-red">一流</em>”建设资金7.7亿】建设世界<em class="s-color-red">一流</em>大学、<em class="s-color-red">一流</em>学科,简称&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;。河南省建设情况如何?16日,河南省人大召开专题会议,听取河南省&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;建设情况。记者从会场了解到,郑州大学、河南大学<em class="s-color-red">双</em><em class="s-color-red">双</em>进入&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;建设高校行列,省财政厅2018年度安排&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;建设资金 ​  <a href="//weibo.com/1734530730/GEdxCcHIM?refer_flag=1001030103_" action-type="fl_unfold" target="_blank">展开全文<i class="wbicon">c</i></a>                </p>
                                <p class="txt" node-type="feed_list_content_full" nick-name="大河报" style="display: none">
                    【大手笔!河南省财政厅2018年度安排“<em class="s-color-red">双</em><em class="s-color-red">一流</em>”建设资金7.7亿】建设世界<em class="s-color-red">一流</em>大学、<em class="s-color-red">一流</em>学科,简称&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;。河南省建设情况如何?16日,河南省人大召开专题会议,听取河南省&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;建设情况。记者从会场了解到,郑州大学、河南大学<em class="s-color-red">双</em><em class="s-color-red">双</em>进入&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;建设高校行列,省财政厅2018年度安排&quot;<em class="s-color-red">双</em><em class="s-color-red">一流</em>&quot;建设资金7.7亿元。<a href="http://t.cn/EzPKTgk"  target="_blank"><i class="wbicon">O</i>大手笔!河南省财政厅2018年度安排“<em class="s-color-red">双</em><em class="s-color-red">一流</em>”建设资金7.7亿</a> <a href="javascript:void(0);" action-type="fl_fold">收起全文<i class="wbicon">d</i></a>
                </p>
                                                <!--card解析-->
<div node-type="feed_list_media_prev">
    <div class="media media-piclist" node-type="fl_pic_list" action-data="uid=1734530730&mid=4295851763028004&pic_ids=6762d6aaly1fwaco8ljn5j20dw0990t1">
                <ul class="m3">
                                <li><img src="//ww1.sinaimg.cn/thumb150/6762d6aaly1fwaco8ljn5j20dw0990t1.jpg" action-data="uid=1734530730&pic_id=6762d6aaly1fwaco8ljn5j20dw0990t1" action-type="fl_pics" suda-data="key=tblog_search_weibo&value=weibo_ss_1_pic"></li>
                    </ul>
    </div>
</div>
<div node-type="feed_list_media_disp">
</div>


<!--/card解析-->
                                <p class="from" >
                                            <a href="//weibo.com/1734530730/GEdxCcHIM?refer_flag=1001030103_" target="_blank" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:wb_time">
                        10月16日 20:52
                        </a>
                                         来自 <a href="http://app.weibo.com/t/feed/1sxHP2" rel="nofollow">专业版微博</a>                </p>
            </div>
            <!--/微博内容-->
        </div>
        <div class="card-act">
            <ul>
                <li><a href="javascript:void(0);" action-type="login" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:fav">收藏</a></li>
                                <li><a href="javascript:void(0);" action-data="allowForward=1&mid=4295851763028004&name=大河报&uid=1734530730" action-type="login" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:repost">转发 19</a></li>
                                <li><a href="javascript:void(0);" action-data="pageid=weibo&amp;suda-data=key%3Dtblog_search_weibo%26value%3Dweibo_h_1_p_p" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:comment" action-type="login">评论 46</a></li>
                <li><a title="赞" action-data="mid=4295851763028004" action-type="login" href="javascript:void(0);" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:like"><i class="icon-act icon-act-praise"></i> <em>29</em></a></li>
            </ul>
        </div>
        <div node-type="feed_list_repeat"></div>
            </div>
</div>
<!--/card-wrap-->

这里以微博ID为例,进行分析,微博ID位于class="name"的a标签中的href中,通过getElementsByClass("name").attr("href")获取到href后,还需使用正则表达式获取到十位数字的微博ID:

//<a href="//weibo.com/1734530730?refer_flag=1001030103_" class="name" target="_blank" nick-name="大河报" suda-data="key=tblog_search_weibo&value=seqid:15397465809059866363|type:1|t:0|pos:1-0|q:%E5%8F%8C%E4%B8%80%E6%B5%81|ext:cate:26,mpos:1,click:user_name">大河报</a>
String Href = link.getElementsByClass("name").attr("href");
String pattern = "/(\\d{10})";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(Href);
String Id;

if (m.find()) {
    Id = m.group(1);
} else {
    Id = "";
     }

下面是其他目标元素的获取,以及置于exce中进行展示:

int k = 1;
Element content = doc.getElementById("pl_feedlist_index");
Elements links = content.getElementsByAttributeValue("action-type", "feed_list_item");
for (Element link : links) {
    try {
    	//此处结合下面catch中的  continue; 实现对“热门文章”(和动态块里的标签种类不同,会执行catch中的代码)过滤;
        String id_href = link.getElementsByClass("name").first().attr("href");
        String pattern = "/(\\d{10})";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(id_href);
        String Id;
        
        if (m.find()) {
            Id = m.group(1);
        } else {
            Id = "";
             }
        
       
        String Name = link.getElementsByClass("name").text();
        String Content = link.getElementsByClass("txt").text();
        String Time = link.getElementsByClass("from").first().getElementsByAttributeValue("target", "_blank").text();
        String PlatForm = link.getElementsByClass("from").first().getElementsByAttributeValue("rel", "nofollow").text();
        String Forward = link.getElementsByClass("card-act").first().getElementsByTag("li").get(1).text();
        String Comment = link.getElementsByClass("card-act").first().getElementsByTag("li").get(2).text();
        String Like = link.getElementsByClass("card-act").first().getElementsByTag("li").get(3).text();
       
        //填入excel中进行展示
    	row = sheet.createRow(k);
        row.createCell(0).setCellValue(Id);
    	row.createCell(1).setCellValue(Name);
    	row.createCell(2).setCellValue(Content); 	
    	row.createCell(3).setCellValue(Time);
    	row.createCell(4).setCellValue(PlatForm);
    	row.createCell(5).setCellValue(Forward);
    	row.createCell(6).setCellValue(Comment);
    	row.createCell(7).setCellValue(Like);                 
        k++;

    } catch (NullPointerException e) {
        continue;
    }
}

至此,微博数据的爬取完成!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值