爱回收二手平台爬虫分析

这个数据采集项目本来是一个外包项目,做完了一阵子老板不要了…所以就把它开源了…

项目地址:https://github.com/yujunjiex/AHSSpider

数据分析结果请见:https://yujunjiex.gitee.io/2019/10/01/爱回收二手平台数据分析

如何获得一件商品的回收报价?

以macbook pro2017 13寸的二手报价过程为例

  1. 来到笔记本(laptop)页面,选中苹果(b52)

image-20190930190638164

  1. 找到macbook pro2017 13寸并进入商品界面(/product/{商品id})

    image-20190930191116572

  2. 根据系统给出的一系列属性进行选择,其中属性分为base-property(处理器,显卡等重要信息),function-property(是否机身进水,严重维修,部件损坏等信息),还有这件商品中没有的quick-property(使用情况——用于快速报价的一个属性)

    image-20190930192029238

  3. 点击「立即估价」得到商品报价信息(inquery/{inquery_key})

    image-20190930192223240

我们需要哪些信息?

  1. 一件商品的「商品id」用于定位页面
  2. 商品页面的属性信息如何获取
  3. 如何post选择的属性
  4. 最后的报价信息如何获取

开始分析

商品的「商品id」如何获取

laptop/b52列出的「笔记本电脑」「苹果」页中的每个li中都有这个商品页的地址(包含id)

image-20190930193323177

所以我们只需对品牌信息进行分页爬取,就能获得每一页中的商品地址(商品id)

商品页面的属性信息

同样页面元素中也有相关的属性信息

image-20190930193906525

但有没有相关的api提供呢?毕竟有api谁还会去解析html页面嘛,用chrome自带的调试工具选中XHR查看异步请求果然有相关的api提供!

image-20190930195417308

这时我们获取到了所有属性的api:

1
2
3
# 属性api
base_property_api = "https://www.aihuishou.com/portal-api/product/inquiry-detail-new/{商品id}"
quick_query_api = "https://www.aihuishou.com/portal-api/product/quick-inquiry?productId={商品id}"

如何post请求

在这个问题之前还有一个问题,就是如何构造这个属性选择的列表?

数据采集过程是自动化的,应根据拿到的属性提前给与属性该如何选择,所以我们需要知道所有商品的属性并集,并提供属性的选择方案。

比如我需要拿到「笔记本电脑」的属性并集的话,我可以获取任意个笔记本电脑商品的属性,放入到set中,最后拿到的就是属性的并集。

最后获取到「笔记本电脑」的属性有:

{‘固态硬盘’, ‘显卡’, ‘开机运行’, ‘边框背板’, ‘颜色’, ‘键盘’, ‘屏幕显示’, ‘购买渠道’, ‘屏幕类型’, ‘国内保修情况’, ‘机械硬盘’, ‘内存’, ‘处理器’, ‘屏幕外观’}

我们就可以根据自己需要对「笔记本电脑」的属性设置选择的默认值。

回到如何post请求上来

先找到「立即估价」这一元素的逻辑,可以看到是跳转到了userinquiry/createnew.html这个页面。但请求前后的页面不一致,怀疑是重定向

image-20190930201032043

所以我们再通过fiddler抓包分析到post请求的构造

p95.png

可以看到这个post请求得到的json数据中有redirectUrl也就是最后的报价信息!但这个请求中的productIds、Ppvids、PhenomenonItemIds和IsEnvironmentRecycling又如何获取呢?

productIds猜测是商品id,Ppvids猜测是属性选择的数组,经过实际分析也证实了猜测。

那其他两个参数呢,这时候只能到「立即估价」的click事件里去看看了= =,经过分析找到了这一段js代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$submit.on("click", function(d) {
d.preventDefault();
var u = $(this);
if (!u.hasClass("disabled") && D) {
if (!c.hasClass("hidden")) {
var p = $.trim(l.val());
if (!s(p))
return;
o.imgCaptcha = p
}
o.PpvIds = e(), // 注意这里还有三个参数
o.PhenomenonItemIds = t(),
o.IsEnvironmentalRecycling = i(),
ahs.PopWindow.Loading(!0),
$.post(a, o, function(e) { // 这里a是url,o是请求的参数
ahs.PopWindow.Hide(),
e.code ? 3001 === e.code ? r(e.data.captchaUrl) : 3002 === e.code && (n(e.data.captchaUrl),
alert("验证码有误")) : location.href = e.data.redirectUrl
})
}
});

o.PhenomenonItemIds = t(),o.IsEnvironmentalRecycling = i(),我们分别找到对应的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function t() {
var e = []
, t = [];
$(".base-property dl").each(function(t, i) {
"True" == $(i).data("isphenomenon") && $(i).find("li").each(function(t, i) {
$(i).hasClass("checked") && "True" == $(i).data("shouldrelease") && (e = e.concat($(i).data("ids")))
})
});
var n = i();
return n || $(".function-property dl li.property-value").each(function() {
$(this).hasClass("checked") ? t = t.concat($(this).data("ids")) : $(this).data("default") && t.push($(this).data("default"))
}),
e = e.concat(t)
}
function i() {
var e = !1;
return $(".select-property").find("li.checked").each(function() {
"True" == $(this).data("isenvironmentalrecycling") && (e = !0)
}),
e
}

看起来就是t()获取function-property选择的数组,i()获取是否有属性为isenvironmentalrecycling的选中(后面发现isenvironmentalrecycling只有在function-property有选择的时候才为true)

function-property属性都是商品已经严重损坏的一些情况,我们这里默认不选择即可。所以我们只需要获取productIds和通过属性api构造Ppvids数组就能得到报价信息。

最后的报价信息如何获取

通过post拿到的redirectUrl即商品报价页

通过分析可以获取报价的api(inquery_key即redirectUrl中最后面的数字)

1
"https://www.aihuishou.com/portal-api/inquiry/{inquery_key}"

测试

image-20190930204306226

测试通过,接下来就是编码任务了!(中间还有一堆的坑= =)

项目地址:https://github.com/yujunjiex/AHSSpider

觉得好的话就打赏Ta一瓶冰阔落吧