美文网首页
神箭手爬虫归纳总结-初级开发,分享爬取一点资讯网站视频的demo

神箭手爬虫归纳总结-初级开发,分享爬取一点资讯网站视频的demo

作者: 文艺范码农 | 来源:发表于2017-08-03 14:52 被阅读0次

    神箭手爬虫通过js来编写,调用神箭手框架的一些api实现某些需求和功能。整段程序的大体框架是这样的:

    var configs = {
        domains: ["要爬取的域名"],
        scanUrls: ["爬虫的入口URL"],
        contentUrlRegexes: [/http:\/\/.*/],//内容页url正则
        helperUrlRegexes: [/http:\/\/.*/], //列表页url正则 可留空
        fields: [
            {
                // 抽取项
                name: "title",
                selector: "抽取规则", //默认使用XPath
                required: true //是否不能为空
            },
            {
                // 抽取项
                name: "content",
                selector: "抽取规则"
            }
        ]
    };
    
    var crawler = new Crawler(configs);
    crawler.start();
    

    1.认识configs对象

    configs对象包括一些成员变量(domains、scanUrls、contentUrlRegexes、helperUrlRegexes)和fields抽取项。然后通过crawler对象包装,开始执行爬虫。

    2.认识domains变量

    定义神箭手应用爬取哪些域名下的网页, 非域名下的网页会被忽略以提高爬取速度。

         // 单个域名
        domains: ["i.youku.com"]
        // 多个域名
        domains: ["i.youku.com", "v.youku.com"],
    

    3.认识scanUrls变量

    定义神箭手应用的入口页url, 神箭手应用会从入口页url开始爬取数据

    // 单个入口页url
        scanUrls: ["http://wallstreetcn.com/"]
    // 多个入口页url
        scanUrls: ["http://baijia.baidu.com/","http://www.demo.com/" ]
    
    1. 认识内容页contentUrlRegexes正则的匹配
      contentUrlRegexes是设置内容页的正则表达式,用来匹配页面中符合这一正则表达式的url。比如http://www.qiushibaike.com/article/117844937,他的正则表达式可以表示为
    contentUrlRegexes:["/http:\/\/www\.qiushibaike\.com\/article\/\d+/"]
    

    可以用在线正则查看匹配是否准确(//之间的字符串为正则表达式)。http://tool.oschina.net/regex/

    5.认识列表页helperUrlRegexes正则的匹配
    helperUrlRegexes是设置列表页的正则表达式,用来匹配页面中符合这一正则表达式的url。比如https://www.leiphone.com/search?s=vr&site=article,他的正则表达式可以表示为

    helperUrlRegexes:["/https:\/\/www\.leiphone\.com\/search\?s=vr&site=article(&page=\d+)?/"]
    

    6.认识fields

    1). 定义内容页的抽取规则
    2). 规则由一个或多个field组成, 一个field代表一个抽取项,也就是说代表一个要存储的字段。
    拿雷锋网的内容页为例:

    fields: [
            {
                // 抽取项名称,以后就是代表数据库中字段的名称
                name: "title",
                // 抽取项别名, 在神箭手控制台预览该条数据的时候会显示
                alias: "爬取的标题",
                // 抽取该项数据的表达式(默认使用XPath来选取节点的内容),其他类型不做赘述,我也只用过这一种方式
                selector: "//h1[contains(@class,'headTit')]",
                // required为true表示该项数据不能为空,默认值为false
                 required: true //如果抽取的数据为空,该条记录过滤掉
            }
        ]
    

    xpath语法介绍:http://www.w3school.com.cn/xpath/xpath_syntax.asp

    7.神箭手回调函数

    imagecallbackFlowchart.png

    (1)beforeCrawl:神箭手应用初始化的时候调用,做一些爬取之前的操作,给http请求加header等
    (2)onChangeProxy:在神箭手应用切换代理IP后调用, 主要用来给HTTP请求添加Header和Cookie等数据,切换代理IP后, 先前HTTP请求添加的Cookie会被清除, 若打算继续使用Cookie, 强烈建议在onChangeProxy回调函数中添加Cookie
    (3)isAntiSpider:判断访问网页时是否被目标网站屏蔽, 如果判断被屏蔽了, 神箭手会切换一次代理IP后自动重新爬取
    (4)afterDownloadPage:在一个网页下载或JS渲染完成之后调用, 主要用来处理网页,可以自定义加入html代码。
    (以上回调一般用不到,默认不写就行。特殊情况除外。)

    下面3个回调是经常用到,需要书写代码的:
    (5)onProcessScanPage:入口页类型的回调,不写默认返回true,在下载完页面之后,会发现符合内容页正则和列表正则的url,添加到待爬队列里。如果返回false,不会自动发现url,需要手动添加url,此url必须符合上边定义的正则表达式。
    (6)onProcessHelperPage:列表页类型的回调,不写默认返回true。同上
    (7)onProcessContentPage:内容页类型的回调,不写默认返回true。同上

    (8)afterDownloadAttachedPage:在一个attachedUrl对应的网页下载或JS渲染完之后调用, 主要用来处理网页。就是页面中又发起的一次异步请求,返回时调用。
    (9)beforeHandleImg:从内容页中抽取到一个抽取项的值之后调用, 对其中包含的img标签进行处理。很多网站对图片设置了延迟加载, 这时就需要在beforeHandleImg回调函数中处理
    (10)beforeCacheImg:在对爬取到的图片url进行托管处理之前调用, 主要对托管的图片url进行处理,应该是在文件下载之前,处理一下地址,比如图片有多种大小类型,可能要的是大图。

    这个回调一般会用到:
    (11)afterExtractField:从内容页中抽取到一个抽取项的值后进行的回调, 在此回调中可以对该抽取项的值进行处理并返回。

    (12)afterExtractPage:在内容页的所有抽取项抽取完成之后, 在此回调函数中对抽取项再进行一次处理或进行其他操作。

    8.内置对象:回调函数中,会有一些参数,以下这几个对象:
    site:当前正在爬取的目标网站对象
    page:当前正在爬取的网页对象

    console:打印控制台日志的,一般用个console.log();
    还有systen、options、shenjian等对象

    9.具体看几个demo例子.......
    神箭手的概念还是比较好理解,但是每个网页的情况都是不同的,对应还得具体来分析,处理的方式也不一样。

    糗事百科简单举例:

    var configs = {
        domains: ["qiushibaike.com"],
        scanUrls: ["https://www.qiushibaike.com/"],
        contentUrlRegexes: [/https:\/\/www\.qiushibaike\.com\/article\/\d+/],//内容页url正则
        helperUrlRegexes: [/https:\/\/www\.qiushibaike\.com\/8hr\/page\/\d+/], //列表页url正则 可留空
        fields: [
            {
                // 抽取项
                name: "title",
                alias : "标题",
                selector: "//div[contains(@class,'author')]/a[2]/h2/text()", //默认使用XPath
                required: true //是否不能为空
            },
            {
                // 抽取项
                name: "content",
                alias : "内容",
                selector: "//*[@id='single-next-link']/div/text()"
            },
            {
                name : "commentCount",
                alias : "评论",
                selector : "//i[contains(@class,'number')]/text()"
            }
          
        ]
    };
    //每抽取一个字段会调用,用于对该字段的再次处理,比如时间再次定义格式
    configs.afterExtractField = function (fieldName, data, page, site) {
        
        return data;
    };
    //抽取完这个内容页的所有字段之后再调用一次
    configs.afterExtractPage = function (page, data, site) {
        
        return data;
    };
    //入口页类型的回调,页面下载完会调用
    configs.onProcessScanPage = function (page, content, site) {
        console.log("onProcessScanPage:入口页");
        return true;
    };
    //列表页类型的回调
    configs.onProcessHelperPage = function (page, content, site) {
        console.log("onProcessHelperPage:列表页");
        site.addUrl("");
        return false;
    };
    //内容页类型的回调
    configs.onProcessContentPage = function (page, content, site) {
        console.log("onProcessContentPage:内容页");
        return false;
    };
    
    var crawler = new Crawler(configs);
    crawler.start();
    

    爬取 一点资讯-视频 爬虫源码:

    var cend = 0;
    var chanel = "u13746";
    function getNowFormatDate() {
            var date = new Date();
            var seperator1 = "-";
            var year = date.getFullYear();
            var month = date.getMonth() + 1;
            var strDate = date.getDate();
            if (month >= 1 && month <= 9) {
                month = "" + month;
            }
            if (strDate >= 0 && strDate <= 9) {
                strDate = "" + strDate;
            }
            var currentdate = year + seperator1 + month + seperator1 + strDate;
            return currentdate;
     }
    var configs = {
        domains: ["yidianzixun.com"],
        scanUrls: ["http://www.yidianzixun.com/channel/u13746"],
        contentUrlRegexes: [
          /http:\/\/www\.yidianzixun\.com\/mp\/content\?id=\d+/
        ],//内容页url正则
        helperUrlRegexes: [
          /http:\/\/www\.yidianzixun\.com\/home\/q\/news_list_for_channel\?channel_id=[a-zA-Z0-9_]+&cstart=\d+&cend=\d+&infinite=true&refresh=1&__from__=pc&multi=5&appid=web_yidian&_=\d+/
        ], //列表页url正则 可留空
    
        fields: [
            {
                name: "title",
                alias : "标题",
                selector : "//div[contains(@class,'left-wrapper')]/h2/text()",
                required : true
    
            },
            {
                name: "publishDate",
                alias : "发布时间",
                selector: "//div[contains(@class,'left-wrapper')]/div[contains(@class,'meta')]/span/text()",
                required : true
            },
            {
                name : "videoUrl",
                alias : "视频播放地址",
              selector : "/html/body/div[2]/div[1]/div[2]/video/@src",
    //             selector : "//div[contains(@class,'left-wrapper')]/div[contains(@class,'video-wrapperr')]/video/@src",
                required : true
            },
            {
              name : "img",
              alias : "缩略图",
              selector : "//div[@id='img_view']/text()",
              required : true,
              sourceType : SourceType.UrlContext
        
            },
            {
              name : "time",
              alias : "时长",//单位:s
              selector : "//div[@id='time_view']/text()",
              sourceType : SourceType.UrlContext
            },
            {
              name : "keyword",
              alias : "关键词",
              selector : "//div[@id='keyword_view']",
              sourceType : SourceType.UrlContext
            }
        ]
    };
    
    configs.afterExtractField = function (fieldName, data, page, site) {
        if(fieldName == "publishDate") {
          var isDate = /\d+\.\d+\.\d+/.exec(data);
          if(!isDate) {
            data = getNowFormatDate();
          }
          else {
            data = data.replace(/\./g, "-");  
          }
        }
        if(fieldName == "keyword") {
          if(data == "undefined") {
            data = "";
          }
        }
        return data;
    };
    
    
    configs.onProcessContentPage = function (page, content, site) {
    
        return false;
    };
    configs.onProcessHelperPage = function (page, content, site) {
        var jsonObj = JSON.parse(content);
        console.log("jsonObj:"+jsonObj);
        if(jsonObj.status != "success") {
           return false;
        }
        var items = jsonObj.result;
        for (var i = 0; i < items.length; i++) {
            if(items[i].hasOwnProperty("url")) {
              var detailUrl = items[i].url;
              var img = items[i].image;
              var time = items[i].duration;
              var keyword = items[i].keywords;
              var htmlStr = '<div id="img_view">'+img+'</div><div id="time_view">'+time+'</div><div id="keyword_view">'+keyword+'</div>';
              var options = {
                method : "GET",
                contextData : htmlStr
              };
              site.addUrl(detailUrl,options);
            }
            
        }
        
        if(cend != null && cend != "") {
          site.addUrl("http://www.yidianzixun.com/home/q/news_list_for_channel?channel_id="+chanel+"&cstart="+cend+"&cend="+(cend+10)+"&infinite=true&refresh=1&__from__=pc&multi=5&appid=web_yidian&_="+Date.parse(new Date()));
          cend = cend + 10;
        }
        return false;
    };
    configs.onProcessScanPage = function (page, content, site) {
        //从入口页获得chanel_id,每个浏览器可能不同,有限制
        chanel = extract(content, "//div[contains(@class,'channel-nav')]/div[contains(@class,'list')]/a[4]/@data-channelid");
        console.log("chanel:"+chanel);
        site.addUrl("http://www.yidianzixun.com/home/q/news_list_for_channel?channel_id="+chanel+"&cstart="+cend+"&cend="+(cend+10)+"&infinite=true&refresh=1&__from__=pc&multi=5&appid=web_yidian&_="+Date.parse(new Date()));
        cend = cend + 10;
        return false;
    };
    
    var crawler = new Crawler(configs);
    crawler.start();
    

    相关文章

      网友评论

          本文标题:神箭手爬虫归纳总结-初级开发,分享爬取一点资讯网站视频的demo

          本文链接:https://www.haomeiwen.com/subject/qegwkxtx.html