zoukankan      html  css  js  c++  java
  • java爬虫系列(二)——爬取动态网页

    java爬虫系列(二)——爬取动态网页

    准备工作

    新手的话推荐使用seimiagent+seimicrawler的爬取方式,非常容易上手,轻松爬取动态网页,目测初步上手10分钟以内吧。

    项目地址

    https://github.com/a252937166/seimicrawler

    网页解析工具地址

    https://github.com/a252937166/seimiagent

    启动网页解析器

    根据系统选择所需文件

    下载好seimiagent,根据自己的操作系统,如果是windows,就用seimiagent.exe,如果是linux,就选择seimiagentmac版本暂时还没有,我的话一般会把seimiagent放在自己的linux服务器上。

    指定端口号启动工具

    linux为例,进入文件所在目录,指定8000端口,./seimiagent -p 8000,即可启动。 
    这里写图片描述

    图(1)

    项目配置

    seimi.properties

    redis.host=127.0.0.1
    redis.port=6379
    redis.password=
    database.driverClassName=com.mysql.jdbc.Driver
    database.url=
    database.username=
    database.password=
    seimiAgentHost=127.0.0.1
    seimiAgentPort=8000
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    找到此配置文件,修改seimiAgentHostseimiAgentPort为自己的地址信息。

    SeimiAgentDemo.java

    package com.ouyang.crawlers;
    
    import cn.wanghaomiao.seimi.annotation.Crawler;
    import cn.wanghaomiao.seimi.def.BaseSeimiCrawler;
    import cn.wanghaomiao.seimi.struct.Request;
    import cn.wanghaomiao.seimi.struct.Response;
    import cn.wanghaomiao.xpath.model.JXDocument;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Value;
    
    /**
     * 这个例子演示如何使用SeimiAgent进行复杂动态页面信息抓取
     * @author 汪浩淼 et.tw@163.com
     * @since 2016/4/14.
     */
    @Crawler(name = "seimiagent")
    public class SeimiAgentDemo extends BaseSeimiCrawler{
    
        /**
         * 在resource/config/seimi.properties中配置方便更换,当然也可以自行根据情况使用自己的统一配置中心等服务
         */
        @Value("${seimiAgentHost}")
        private String seimiAgentHost;
    
        @Value("${seimiAgentPort}")
        private int seimiAgentPort;
    
        @Override
        public String[] startUrls() {
            return new String[]{"https://www.baidu.com"};
        }
    
        @Override
        public String seimiAgentHost() {
            return this.seimiAgentHost;
        }
    
        @Override
        public int seimiAgentPort() {
            return this.seimiAgentPort;
        }
    
        @Override
        public void start(Response response) {
            Request seimiAgentReq = Request.build("http://manhua.fzdm.com/2/889/","getHtml")
                    .useSeimiAgent()
    //                告诉SeimiAgent针对这个请求是否使用cookie,如果没有设置使用当前Crawler关于cookie使用条件作为默认值。
    //                .setSeimiAgentUseCookie(true)
                    //设置全部load完成后给SeimiAgent多少时间用于执行js并渲染页面,单位为毫秒
                    .setSeimiAgentRenderTime(5000);
            push(seimiAgentReq);
        }
    
        /**
         * 打印网页信息
         * @param response
         */
        public void getHtml(Response response){
            try {
                System.out.println(response.getContent());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    找到这个demo文件,注意.useSeimiAgent(),这就是表示需要使用seimiagent来解析动态网页了,此外还可以设置cookieparammeta这些参数。 
    我们使用getHtml()这个回调函数来打印网页信息,对比一下看看,有没有顺利解析成功。

    分析原网页代码

    我们使用chrome浏览器的network查看网页原始代码。 
    这里写图片描述

    图(2)
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="utf-8">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="Content-Language" content="utf-8" />
    <meta content="all" name="robots" />
    <title>海贼王889话 风之动漫</title>
    <meta name="keywords" content="海贼王889话 " />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Cache-Control" content="no-transform" />
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <meta name="applicable-device" content="pc,mobile" />
    <meta name="HandheldFriendly" content="true" /> 
    <meta property="og:title" content="海贼王889话"/>
    <meta property="og:type" content="book"/>
    <meta property="og:url" id="readurl" content="http://manhua.fzdm.com/2/889/" />
    
    <link rel="stylesheet" href="//static.fzdm.com/pure/pure-min.css">
    <!--[if lte IE 8]>
        <link rel="stylesheet" href="//static.fzdm.com/pure/grids-responsive-old-ie-min.css">
    <![endif]-->
    <!--[if gt IE 8]><!-->
        <link rel="stylesheet" href="//static.fzdm.com/pure/grids-responsive-min.css">
    <!--<![endif]-->
    <link rel="stylesheet" href="//static.fzdm.com/pure/fzdm.css">
    <link rel="icon" href="//static.fzdm.com/favicon.ico" mce_href="//static.fzdm.com/favicon.ico" type="image/x-icon">
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="apple-touch-icon" href="//static.fzdm.com/apple-touch-icon-144x144.png" />
    
    <style>
    .logo {
        top: -2px;
        height: 70px;
        overflow: hidden;}
    
    .logo img{height:77px}
    #header {
      height: 70px;
    }
    #header ul {
      top: 8px;}
      .pure-menu.pure-menu-open, .pure-menu.pure-menu-horizontal li .pure-menu-children {
         text-align: left;
         height: 70px;
         background: none;
       /* border: 1px solid #b7b7b7; */
     }
    
    
    </style>
    
    <script>
    var _hmt = _hmt || [];
    (function() {
    var hm = document.createElement("script");
    hm.src = "//hm.baidu.com/hm.js?cb51090e9c10cda176f81a7fa92c3dfc";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
    })();
    </script>
    
    </head>
    <body>
        <!--[if lt IE9]>
        <script src="//static.fzdm.com/html5shiv.min.js"></script>
        <![endif]-->
    <script src="//static.fzdm.com/jquery-1.9.1.min.js?v=1"></script>
    <script src="//static.fzdm.com/fzdm.js?v=1"></script>
    <script src="//static.fzdm.com/u.js"></script>
    
    <script src="//dup.baidustatic.com/js/dm.js"></script>
    <div id="header">
    <div class="pure-g">
    <div class="pure-menu pure-menu-open pure-menu-horizontal">
    <div class="logo">
    <a href="//www.fzdm.com"><img src="//static.fzdm.com/css/logo.png" alt="风之动漫" /></a>
    </div>
    <ul>
    <li><a href="//www.fzdm.com/"> 首页</a></li>
    <li><a href="//news.fzdm.com/">动漫新闻</a></li>
    <li><a href="//manhua.fzdm.com/">在线漫画</a></li>
    <li><a href="//flash.fzdm.com/">动漫flash</a></li>
    
    </ul>
    
                </div>
                </div>
                </div>
            </div>
    
        <center>
    <!-- 广告位:顶部960*90 -->
    
    </center>
    
    <br>
    
    
    <br>
    <div id="weizhi">位置:<a href="//www.fzdm.com">首页</a> - <a href="../../">在线漫画</a> - <a href="../">海贼王</a> - 海贼王889话<h4 style="float:right;margin-right: 100px;"><a href="#comments">海贼王889话讨论区</a></h4></div>
    <div id="mh">
    <h1>海贼王889话</h1>
    
    <div id="mhimg0"><h2><a href="//manhua.fzdm.com/2/889/">《无法观看》请点击此处~</a></h2></div>
    
    
    <center>
    
    <div id="share">
    <div class="bdsharebuttonbox"><a href="#" class="bds_more" data-cmd="more">分享<strong>海贼王889话漫画</strong>到:</a><a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a><a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a><a href="#" class="bds_sqq" data-cmd="sqq" title="分享到QQ好友">QQ好友</a><a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">微博</a><a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯</a><a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a><a href="#" class="bds_fbook" data-cmd="fbook" title="分享到Facebook">Facebook</a><a href="#" class="bds_baidu" data-cmd="baidu" title="分享到百度搜藏">百度搜藏</a><a href="#" class="bds_bdhome" data-cmd="bdhome" title="分享到百度新首页">百度首页</a><a class="bds_count" data-cmd="count"></a></div>
    </div>
    
    <div id="ad">
    <script src='//m.xmshqh.com/fz2.js'></script>
    </div>
    
    </center>
    <div class="navigation">
    <a href="index_0.html" id="mhona">第1页</a><a href="index_1.html">2</a><a href="index_2.html">3</a><a href="index_3.html">4</a><a href="index_4.html">5</a><a href="index_5.html">6</a><a href="index_6.html">7</a><a href="index_7.html">8</a><a href="index_8.html">9</a><a href="index_9.html">10</a><a href="index_10.html">11</a><a href="index_11.html">12</a><a href="index_12.html">13</a><a href="index_13.html">14</a><a href="index_14.html">15</a><a href="index_15.html">16</a><a href="index_16.html">17</a><a href='index_1.html' id="mhona">下一页</a></div>
    
    <br />
    <br />
    <script type="text/javascript">
            document.write('<a style="display:none!important" id="tanx-a-mm_10028503_120355_28042038"></a>');
            tanx_s = document.createElement("script");
            tanx_s.type = "text/javascript";
            tanx_s.charset = "gbk";
            tanx_s.id = "tanx-s-mm_10028503_120355_28042038";
            tanx_s.async = true;
            tanx_s.src = "//p.tanx.com/ex?i=mm_10028503_120355_28042038";
            tanx_h = document.getElementsByTagName("head")[0];
            if(tanx_h)tanx_h.insertBefore(tanx_s,tanx_h.firstChild);
    </script><script type="text/javascript">
            document.write('<a style="display:none!important" id="tanx-a-mm_10028503_120355_28058018"></a>');
            tanx_s = document.createElement("script");
            tanx_s.type = "text/javascript";
            tanx_s.charset = "gbk";
            tanx_s.id = "tanx-s-mm_10028503_120355_28058018";
            tanx_s.async = true;
            tanx_s.src = "//p.tanx.com/ex?i=mm_10028503_120355_28058018";
            tanx_h = document.getElementsByTagName("head")[0];
            if(tanx_h)tanx_h.insertBefore(tanx_s,tanx_h.firstChild);
    </script>
    <script type="text/javascript">
            document.write('<a style="display:none!important" id="tanx-a-mm_10028503_120355_28066012"></a>');
            tanx_s = document.createElement("script");
            tanx_s.type = "text/javascript";
            tanx_s.charset = "gbk";
            tanx_s.id = "tanx-s-mm_10028503_120355_28066012";
            tanx_s.async = true;
            tanx_s.src = "//p.tanx.com/ex?i=mm_10028503_120355_28066012";
            tanx_h = document.getElementsByTagName("head")[0];
            if(tanx_h)tanx_h.insertBefore(tanx_s,tanx_h.firstChild);
    </script>
    <br />
    
    
    <!-- <div id="comments"></div> -->
    
    
    <br><br>
    <script charset="gbk" src="//p.tanx.com/ex?i=mm_10028503_120355_41360495"></script><br /><br />
    <br />
    
    <br /><div id="weizhi">热门漫画导航: <a href='//manhua.fzdm.com/91/' target=_blank>美食的俘虏漫画</a> - <a href='//manhua.fzdm.com/7/ 'target=_blank>死神漫画</a>  - <a href='//manhua.fzdm.com/39/' target=_blank>进击的巨人漫画</a> - <a href='//manhua.fzdm.com/35/' target=_blank>家庭教师漫画</a> - <a href="//manhua.fzdm.com/27/" target=_blank>妖精的尾巴漫画</a>  - <a href="//manhua.fzdm.com/1/" target=_blank>火影忍者漫画</a>  - <a href='//manhua.fzdm.com/53/' target=_blank>黑子的篮球漫画</a>   - <a href='//manhua.fzdm.com/45/' target=_blank>恶魔奶爸漫画</a> - <a href='//manhua.fzdm.com/51/' target=_blank>史上最强弟子兼一漫画</a> - <a href='//manhua.fzdm.com/74/' target=_blank>王者天下漫画</a> - <a href='//manhua.fzdm.com/56/' target=_blank>七原罪漫画</a> - <a href='//manhua.fzdm.com/141/' target=_blank>暗杀教室漫画</a></div>
    <div id="mhimg1"></div>
    <script type="text/javascript">var mhurl = "2017/12/22064917941533.jpg";
    var mhss = getCookie("picHost");
    if (mhss == "") {
        mhss = "p1.xiaoshidi.net";
    }
    if (mhurl.indexOf("2015") != -1 || mhurl.indexOf("2016") != -1|| mhurl.indexOf("2017") != -1 || mhurl.indexOf("2018") != -1){
    
    }else{
        mhss = mhss.replace(/p1/,"p0");
    };
    
    var mhpicurl = mhss+"/"+mhurl;
    if (mhurl.indexOf("http") != -1){
        mhpicurl = mhurl;
    };
    function nofind(){
    
    var img=event.srcElement;
    
    img.src="http://p1.xiaoshidi.net/"+mhurl;
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    document.cookie = "picHost=0;path=/;domain=fzdm.com;expires="+exp.toGMTString();
    img.onerror=null;
    };
    $("#mhimg0").html('<a href="index_1.html"><img src="http://'+mhpicurl+'" id="mhpic" alt="海贼王889话" onerror="nofind();" /></a>');
    
    var mhurl1 = "2017/12/22064917942026.jpg";
    mhpicurl = mhss+"/"+mhurl1;
    $("#mhimg1").html('<img src="http://'+mhpicurl+'" width="0" height="0" id="mhpic1" />');
    
    </script>
    
    <br />
    <br />
    <br />
    <script>if (document.location.protocol == "http:"){
    window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"海贼王889话 风之动漫","bdUrl":"//manhua.fzdm.com/2/889/","bdDesc":"海贼王889话","bdMini":"2","bdMiniList":false,"bdSign":"","bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
    };
    </script>
    </div>
    
    <div class="clear"></div>
    <div id="footer">
    <div id="hd">
    <div class="bg"></div>
    <br><a href="//www.fzdm.com/about">关于我们</a> | <a href="//www.fzdm.com/lianxi">联系我们</a> | <a href="//www.fzdm.com/map">网站地图</a><br />
    Copyright &#9426; 2014-2015 风之动漫 版本beta 0.3<br />
    </div>
    </div>
    
    <div style="display:none;" ><script src="//static.fzdm.com/stat.js"></script></div>
    
    </body>
    </html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226

    请注意这段代码

    <div id="mhimg0"><h2><a href="//manhua.fzdm.com/2/889/">《无法观看》请点击此处~</a></h2></div>
    
    • 1
    • 2

    如果直接爬取原网页,肯定没法获取图片的,那么图片从哪来呢?

    var mhurl = "2017/12/22064917941533.jpg";
    var mhss = getCookie("picHost");
    if (mhss == "") {
        mhss = "p1.xiaoshidi.net";
    }
    if (mhurl.indexOf("2015") != -1 || mhurl.indexOf("2016") != -1|| mhurl.indexOf("2017") != -1 || mhurl.indexOf("2018") != -1){
    
    }else{
        mhss = mhss.replace(/p1/,"p0");
    };
    
    var mhpicurl = mhss+"/"+mhurl;
    if (mhurl.indexOf("http") != -1){
        mhpicurl = mhurl;
    };
    function nofind(){
    
    var img=event.srcElement;
    
    img.src="http://p1.xiaoshidi.net/"+mhurl;
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    document.cookie = "picHost=0;path=/;domain=fzdm.com;expires="+exp.toGMTString();
    img.onerror=null;
    };
    $("#mhimg0").html('<a href="index_1.html"><img src="http://'+mhpicurl+'" id="mhpic" alt="海贼王889话" onerror="nofind();" /></a>');
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    这一段js代码在网页加载完后自动运行,修改了<div id="mhimg0"></div>的内容,才有了图片。 
    js没有多余请求,只是修改了网页内容,这种情况如果想直接java解析,只能用正则,而且如果js代码稍有变化,正则解析就不行了。所以针对这种网页,直接用SeimiAgent把js渲染之后的网页返回给我们是最好的处理方式。

    Boot.java

    package com.ouyang.main;
    
    import cn.wanghaomiao.seimi.core.Seimi;
    
    /**
     * @author 汪浩淼 [et.tw@163.com]
     * @since 2015/10/21.
     */
    public class Boot {
        public static void main(String[] args){
            Seimi s = new Seimi();
            s.goRun("seimiagent");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    goRun("seimiagent");填写对用爬虫名就行了。 
    启动main函数: 
    这里写图片描述

    图(3)

    seimiagent的解析信息, windows版本是后台运行,没有解析信息。 
    控制台信息: 
    这里写图片描述
    图(4)
    <div id="mhimg0"><a href="index_1.html"><img src="http://p1.xiaoshidi.net/2017/12/22064917941533.jpg" id="mhpic" alt="海贼王889话" onerror="nofind();"></a></div>
    • 1

    这段代码,很明显表示,网页信息已经是成功解析后的了。 
    总的来说这套爬虫框架还是很简单的,想要深入了解框架的同学,可以看看下一篇关于实战的文章。

    同系列文章

    java爬虫系列(一)——爬虫入门 
    java爬虫系列(三)——漫画网站爬取实战 
    java爬虫系列(四)——动态网页爬虫升级版 
    java爬虫系列(五)——今日头条文章爬虫实战

  • 相关阅读:
    250 浅拷贝Object.assign(target, ...sources),深拷贝
    249 递归:概念,利用递归求1~n的阶乘,利用递归求斐波那契数列,利用递归遍历数据
    248 闭包:概念,作用,案例,思考题案例,chrome 中调试闭包
    247 高阶函数 之 函数可以作为参数传递
    246 JavaScript严格模式
    245 改变函数内部 this 指向:call,apply,bind,call、apply、bind 三者的异同
    244 函数内部的this指向:6种
    243 函数:函数的3种定义方式,函数的6种调用方式
    242 Object.defineProperty
    241 获取对象的属性名:Object.keys(对象)
  • 原文地址:https://www.cnblogs.com/xinxihua/p/13855615.html
Copyright © 2011-2022 走看看