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

神箭手爬虫通过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.神箭手回调函数

神箭手爬虫归纳总结-初级开发,分享爬取一点资讯网站视频的demo_第1张图片
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 = '
'+img+'
'+time+'
'+keyword+'
'; 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)