Node.js:request+cheerio爬虫爬取免费代理

背景

在极客学院的微信公众号上看到了一个Node.js写爬虫的入门教程——用nodejs去爬一下A站老司机的文章,感觉挺有意思,于是动手写一下。

又想起有位大神用python写过一个抓免费代理的爬虫,于是模仿一下,用nodejs来实现。

依赖库

  • request:发请求,下载网页用的,类似于python的urllib2
  • cheerio:解析网页用的,语法和jquery相似,类似于python的beautifulsoup。

直接用npm下载即可

npm install request --save
npm install cheerio --save

程序功能

从百度到的提供免费代理的网站上爬取免费代理,并通过访问静态资源的方式检测代理是否可用,将可用的代理存放到本地文件当中。

与python的不同

用python写过不少爬虫,本来以为这次会非常轻松的完成,不过失算了。

由于nodejs的单线程异步特性,如果不加思考直接像python那么写,那么request请求还没回来的时候下面的代码就已经执行完了,保存的总是空的。

所以得做一些小手脚让它等待异步函数执行完毕再运行剩下的代码。我采用的办法是用标志量。

更好的解决办法应该是用promise,不过我比较愚鲁,看了半天愣是没看懂,希望不久的将来能领悟吧……

代码

放github上了https://github.com/kongtianyi/freeProxySpider

var request = require("request");
var cheerio = require("cheerio");
var fs = require("fs");

var proxys = [];  //保存从网站上获取到的代理
var useful = [];  //保存检查过有效性的代理


/**
 * 获取www.xicidaili.com提供的免费代理
 */
function getXici() {
    url = "http://www.xicidaili.com/nn";  // 国内高匿代理

    request ({
        url: url,
        method: "GET",
        headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36'
        } //给个浏览器头,不然网站拒绝访问
    }, function(error, response, body) {
        if(!error) {
            var $ = cheerio.load(body);
            var trs = $("#ip_list tr");
            for(var i=1;i<trs.length;i++) {
                var proxy = {};
                tr = trs.eq(i);
                tds = tr.children("td");
                proxy['ip'] = tds.eq(1).text();
                proxy['port'] = tds.eq(2).text();
                var speed = tds.eq(6).children("div").attr("title");
                speed = speed.substring(0, speed.length-1);
                var connectTime = tds.eq(7).children("div").attr("title");
                connectTime = connectTime.substring(0, connectTime.length-1);
                if(speed <= 5 && connectTime <= 1) { //用速度和连接时间筛选一轮
                    proxys.push(proxy);
                }
            }
        }
        check();
    });
}

/**
 * 过滤无效的代理
 */
function check() {
    //尝试请求百度的静态资源公共库中的jquery文件
    var url = "http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js";
    var flag = proxys.length;  //检查是否所有异步函数都执行完的标志量
    for(var i=0;i<proxys.length;i++) {
        var proxy = proxys[i];
        request({
            url: url,
            proxy: "http://" + proxy['ip'] + ":" + proxy['port'],
            method: 'GET',
            timeout: 20000  //20s没有返回则视为代理不行
        }, function (error, response, body) {
            if(!error) {
                if (response.statusCode == 200) {
                    //这里因为nodejs的异步特性,不能push(proxy),那样会存的都是最后一个
                    useful.push(response.request['proxy']['href']);
                    console.log(response.request['proxy']['href'], "useful!");
                } else {
                    console.log(response.request['proxy']['href'], "failed!");
                }
            } else {
                //console.log("One proxy failed!");
            }
            flag--;
            if (flag == 0) {
                saveProxys();
            }
        });
    }
}

/**
 * 把获取到的有用的代理保存成json文件,以便在别处使用
 */
function saveProxys() {
    fs.writeFileSync("proxys.json", JSON.stringify(useful));
    console.log("Save finished!");
}

getXici();  //启动这个爬虫
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孔天逸

没有钱用,只能写写博客这样子~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值