有时候我们为了方便从网页中批量或者自动化的获取数据,以代替繁重的重复的人力劳动。那么我们就需要考虑使用自动的网络爬虫抓取数据,解放重复的劳动。
数据爬虫
原理
当我们想爬取网页中的某一个或者多个数据时,通常都是我们能够在页面中直接看到的(暂不考虑特殊情况)。这时候如果该数据不是图片或者flash类型的数据,那么我们可以在网页源代码
中看到这些数据。可以尝试找个网页,使用审查元素功能,则可以看到该区域对应的源代码,以及想要获取的数据。
使用curl等方法获取到html之后,可以通过解析dom树甚至正则匹配(这种方法略显笨拙)的方法获取想要的数据。通常可以使用id做唯一匹配,如果没有id可以使用则一般尽量使用唯一的class属性,或者根据相对某个唯一元素的相对位置来判断。最终获取到想要的元素之后可以获取想要的内容或者attr等。
异步加载的数据
但是往往事情并不是遂人愿,许多网站特别是电商网站都通过异步的方法加载数据,这个时候直接获取html解析往往拿不到数据或者拿不到正确的数据,需要根据具体情况特殊处理。
AJAX加载的数据
此时依然可以使用审查元素的页面,切换到网络的选项卡中,刷新页面,此时可以看到页面加载过程中的所有http请求,异步数据一般为XHR类型,选择XHR类型筛选可以帮助尽快找到AJAX的接口。找到相应的接口可以分析后可以直接爬取相应的接口也可以获取数据。
接口获取数据受限
但是往往接口所需的参数特别诡异并且不好分析,直接请求接口容易被block。此时需要模拟整个请求的过程,等待数据加载完毕,再解析html从而获取数据。phantomjs支持这种方式爬取数据,当然还有好多高级的功能可以自己查看官网doc。
phanstomjs安装
访问phantomjs官网下载对应操作系统的二进制可执行文件即可
数据爬取
以爬取淘宝数据举例,爬取价格和月销量。其他平台操作方法类似,修改js脚本即可。
爬取某家店铺的360儿童手表6S的价格和销量,解析后的URL为:https://item.taobao.com/item.htm?spm=a230r.1.14.13.9aab031wsUho6&id=562207966090&sku=1627207:829426108,122216431:27772,149204407:3269303,150596106:134855087
。需要注意的是这个URL可能会有改动和下线,具体情况可能与下面描述有出入,可以使用自己的一个URL即可。
phantomjs解析执行的js如下:
var webPage = require('webpage');
var system = require('system');
if (system.args.length === 1) {
console.log('Usage: phantomjs tb.js ');
phantom.exit();
}
var page = webPage.create();
var url = system.args[1];
// 可以再此修改UA
page.settings.userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36";
var count = 0, max = system.args[2];
function load() {
page.includeJs('http://code.jquery.com/jquery-1.11.0.min.js', function() {
count++;
// 引用jquery方便dom选择
var result = page.evaluate(function() {
var obj = Object();
// 月销量
obj.sell_count = $("#J_SellCounter").text();
// 促销价格
obj.price = $("#J_PromoPriceNum").text();
if (obj.price === "") {
// 没有促销价格则使用普通价格
obj.price = $("#J_StrPrice").find(".tb-rmb-num").text();
}
if ($(".error-notice-hd").text() === "很抱歉,您查看的宝贝不存在,可能已下架或者被转移。") {
obj.price = "-1.00";
obj.sell_count = "-1";
}
if ($(".J_TOffSale .tb-hint strong").text() === "此宝贝已下架") {
obj.price = "-1.00";
obj.sell_count = "-1";
}
if (obj.sell_count === "-" || obj.price === "") {
// 数据尚未加载完成,返回空字符串即可
return ""
}
return JSON.stringify(obj);
});
if (result === "" && count < max) {
// 如果尚未加载完成,则等待1s后重试
setTimeout(load, 1000);
return;
}
// 输出爬取的结果
console.log(result);
// 调试时可以渲染出图片
// page.render("tb.png");
phantom.exit();
});
}
// 打开url,解析数据
page.open(url, function(status) {
if(status !== "success") {
console.info(status);
phantom.exit();
}
setTimeout(load, 1000);
});
上述代码保存为tb.js,则可以通过执行下述命令爬取数据:
phantomjs tb.js https://item.taobao.com/item.htm\?spm\=a230r.1.14.13.9aab031wsUho6\&id\=562207966090\&sku\=1627207:829426108,122216431:27772,149204407:3269303,150596106:134855087 5
当时执行时的结果为:
{"sell_count":"12","price":"791.01"}
即月销量12,价格为791.01
常见问题
大部分网站都是反爬虫的,一般是针对IP的,登陆可以解决部分问题,但是也会触发对单个用户的block。爬虫需要控制速度以避免IP被封,或者使用多个代理轮换爬取,但是代价略大。phantomjs支持使用代理,加上参数--proxy=address:port --proxy-auth=user:password
即可。
对于登陆限制的,一般可以通过cookie解决。可以现在浏览器中登陆账号,然后复制相应的cookie信息,放在请求中。但是cookie登陆总有过期的时候,长期的爬虫可能需要自动登录获取cookie,或者避免这种方法。
常用电商URL分析
京东
URL规则
京东URL一般https://item.jd.com/x.html
其中x
代表京东商品编号
天猫
URL规则
天猫URL一般https://detail.tmall.com/item.htm?spm=balabala&id=x&skuId=y
其中spm参数可以不用管,保留即可;x
代表商品id,一般一个商品页面一个id;y
代表一个id下面的不同sku,即一个页面中多个可选的商品选项
淘宝
URL规则
淘宝URL一般https://item.taobao.com/item.htm?spm=balabala&id=x&sku=y
其中spm参数可以不用管,保留即可;x
代表商品id,一般一个商品页面一个id;y
代表一个id下面的不同sku,即一个页面中多个可选的商品选项
获取淘宝中的sku信息
但是淘宝中的sku参数,即y
一般在URL中看不到,如果不指定商品sku,则显示的价格可能是一个范围的值。想要获取sku信息,需要在页面中检查元素获取:
使用chrome浏览器打开淘宝链接,可以去掉不必要的参数,只留下id参数即可,类似
https://item.taobao.com/item.htm?id=x
对想要选择的商品选项点击右键,找到检查元素
把复制出来的值作为sku参数y放置在URL后面作为sku参数:
https://item.taobao.com/item.htm?id=x&sku=y
如果有多重选项,则需要遍历每种选项,分别获得sku的值
y
和z
,分别放置在URL后面作为sku参数:https://item.taobao.com/item.htm?id=x&sku=y:z
则最终得到的URL可以唯一确认一个商品
国美
URL规则
国美URL一般http://item.gome.com.cn/x-y.html
其中x
代表商品id,一般一个商品页面一个id;y
代表一个id下面的不同sku,即一个页面中多个可选的商品选项
苏宁
URL规则
苏宁URL一般https://product.suning.com/x/y.html
其中x
代表店铺id,如果为0000000000
则表示自营产品;y
代表不同商品和sku
亚马逊
URL规则
亚马逊URL规则一般https://www.amazon.cn/dp/x
其中x
代表商品的唯一标识ASIN