Chrome扩展入门-淘宝评论抓取

淘宝问大家功能居然要appkey权限

Posted by tsengkasing on 2017-02-21

爱立信俱乐部给小朋友练手的一个小插件

需求文件下载 这里

Chrome 扩展入门

由于本次需求是一款在淘宝和天猫使用的查询评论插件,360安全浏览器和极速浏览器好像都是以chromium为内核的,故在此直接开发Chrome扩展。

这里要非常感谢360把Chrome扩展的开发文档翻译了,传送门

创建并加载一个应用

1.在本地磁盘新建一个目录,之后所有的资源文件都会放在里面。
2.在该目录底下创建一个名称为manifest.json的文本文件。

接下来我们创建一个HelloWorld扩展程序

首先新建一个文件夹,我们取名为helloworld,然后在文件夹内新建一个manifest.json文件和一个popup.html文件

在manifest.json文件内填入以下内容:

1
2
3
4
5
6
7
8
9
10
{
"name": "Hello World",
"version": "1.0",
"manifest_version": 2,
"description": "A Hello world Chrome Extension.",
"browser_action": {
"default_title" : "Hello World",
"default_popup" : "popup.html"
}
}

在popup.html文件内填入以下内容:(其实就是一个任意的html

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

打开Chrome,在地址栏中输入chrome://extensions/进入扩展程序页面,
勾上开发者模式,然后点击加载已解压的扩展程序,在弹出的框中选择我们刚才新建的文件夹(我们创建的json文件和html文件在里面)

加载成功后,可以在右上角看到我们的新扩展应用的图标,按下后会弹出刚才我们创建的html文件渲染后的样子。


helloworld 应用结束


根据教程以及该插件的需求,我的manifest.json文件设置为如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"name": "Shop-helper-taobao",
"version": "1.0",
"manifest_version": 2,
"description": "An extension which helps watching the comments while browsing items.",
"browser_action": {
"default_icon" : "img/star.ico",
"default_title" : "淘宝助手",
"default_popup" : "html/popup.html"
},
"permissions": [
"https://www.baidu.com/",
"https://*.taobao.com/",
"https://*.tmall.com/",
"activeTab",
"tabs"
],
"background": {
"scripts": ["js/jquery-3.1.1.min.js", "js/background.js"]
},
"content_scripts": [{
"matches": ["https://s.taobao.com/*"],
"css": ["mdl/material.min.css", "css/styles.css"],
"js": ["mdl/material.min.js", "js/jquery-3.1.1.min.js", "js/main.js"],
"run_at" : "document_idle"
}]
}

name,version,description大家都清楚,

然后manifest_version是官方要求填写2

browser_action是在点击插件图标时的相应,设置了popup就会弹出一个小框框

比如这样

permissions是指插件的权限,这里我填写了淘宝和天猫的网址,用于获取权限来爬去评论数据。还有tab是读取浏览器标签的权限,加上百度的网址的缘由我后面再说。

background填写在此处的脚本会在浏览器打开之后就在后台运行,如果需要一直在后台静默运行,把脚本添加至此处即可。

content_scripts是我们的重头戏。

因为需求是需要在鼠标移到图片上就即时爬取信息,我们需要时刻关注鼠标的位置,这就需要content_script。

Content scripts是在Web页面内运行的javascript脚本。通过使用标准的DOM,它们可以获取浏览器所访问页面的详细信息,并可以修改这些信息。

我在这里填写了
"matches": ["https://s.taobao.com/*"]
是当用户在淘宝搜索的时候,该脚本才会激活。


在构建页面的组件的时候,我采用了体积微小的Google官方出品的Material Design组件 - material-design-lite.

传送门 MATERIAL DESIGN LITE

使用的时候只要includematerial.min.cssmaterial.min.js两个文件即可。


至于run_at是指这个脚本加载的时机,如果是document_idle,浏览器会在document_end和发出window.onload事件之间的某个时机注入。具体的时机取决与文档加载的复杂度,为加快页面加载而优化。

本次我们的代码集中在main.js这个文件里面。

构建弹窗

通过查看在淘宝搜索物品的页面,要捕捉用户鼠标移到图片上面的话,主要是有两个方法

1.时刻检测鼠标的坐标。

2.对每个需要监听的位置添加一个事件,通过事件触发。

由于不同窗口大小,坐标位置也不一样,不好判定,我采用了第二个方法。

通过观察该页面的DOM结构,查找出了每一个商品图片的特点

先用class定位到每一个商品div,再对每一个div里面的图片img标签添加onmouseenter事件。

1
2
3
4
5
6
7
8
var items = $('.pic-link.J_ClickStat.J_ItemPicA[data-href]');
for (var i in items) {
if (!isNaN(i)) {
items[i].onmouseenter = function() {
popup(this);
};
}
}

随后发现,筛选出来的只有36个商品,然而当我们往下滚动的时候,会陆续获取更多的商品,当我滚动页面到底部的时候,出现了48个商品,然后在我们刚打开页面的时候,只有36个,这样如果我在页面刚出来就添加事件监听的话,会遗漏还没有加载的12个商品,这个问题暂时先忽略。

以及直接遍历筛选结果还会有length和prevObject等元素,故判断了是否是数字isNaN().

接下来,当鼠标移动到图片的时候,会触发popup函数,我们将在popup函数中创建一个长条框,并显示评论内容。

在popup函数中我把this作为参数传进去了,主要是用于获得该商品div里面的href这个属性的内容,因为这个是后面用来获取itemID和sellerID的地方。

按照面向对象的思想,我创建了一个类FloatingFrame.由于没有必要重复创建和删除同一个框框,我的想法是一开始就创建好这个框框并隐藏,每次事件触发时,移动到目标位置并解除隐藏,关闭的时候再次隐藏,同时使用单例模式来更好的管理这个长条框。

爬取天猫的评论

在寻找需要爬取的内容时,我们使用地表最强浏览器Chrome的强大的开发者工具。

我打开了一个刚才搜索列表中的一个天猫商品的页面,找到评论的位置,使用Chrome的开发者工具,清空Network里面的内容

然后点击图片这个Radio Button之后,查看NetWork的记录,可以清楚的看到第一条记录

查看返回的内容可以看到,这正是我们需要的评论记录!

继续展开这个JSON数组,更加确信了!

那么,我们要如何获取这个数据呢,查看这个网络记录的header


根据这些记录,我们就可以发送同样的请求,获取评论信息,然后进行页面渲染到我们创建的长条框中.

这个请求中必须的参数是URL以及若干个Query String Parameters
由图中可以看到,该请求的URL是https://rate.tmall.com/list_detail_rate.htm

而几个请求参数中,itemID和SellerID是查询的关键,经过我自己私下的测试,发现spuID和ua这两个参数好像无关紧要,于是我舍弃了,还有经过和查看’追评’评论的请求对比,发现这两个请求的URL和大部分参数都一样,只有appendpicture这两个参数不一样,所以获取天猫的图片评论和追评评论的方法可以写成同一套,然后只要区分这两个参数即可。

我写的爬取方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
getCommentDataFromTmall(type) {
$.ajax({
url: this.item.getAttribute('href'),
type: 'GET',
success: function(data) {
let itemId;
let sellerId;
try {
itemId = (this.tmall_itemId_reg.exec(data))[0].slice(8, -1);
sellerId = (this.tmall_sellerId_reg.exec(data))[0].slice(10, -1);
console.log(itemId);
console.log(sellerId);
} catch (e) {
console.log('[ERROR] can not get itemId & sellerId');
console.log(e);
}
$.ajax({
url: 'https://rate.tmall.com/list_detail_rate.htm',
type: 'GET',
data: {
itemId: itemId,
sellerId: sellerId,
order: 3,
currentPage: 1,
append: type === COMMENT_PHOTO ? 0 : 1,
content: 1,
tagId: '',
posi: '',
picture: type === COMMENT_PHOTO ? 1 : 0,
itemPropertyId: '',
itemPropertyIndex: '',
userPropertyId: '',
userPropertyIndex: '',
rateQuery: '',
location: '',
needFold: 0,
_ksTS: '1486045299647_2183',
callback: 'rate_tmall'
},
success: function(data) {

let comment = data.slice(14, -1);
try {
comment = (JSON.parse(comment));
console.log(comment.rateDetail.rateCount);
} catch (e) {
console.log(e);
return;
}

let list;
let rendered_html;
switch (type) {
case COMMENT_PHOTO:
list = document.getElementById('show-panel');
rendered_html = this.renderCommentWithPhotoFromTmall(comment.rateDetail.rateList);
break;
case COMMENT_APPEND:
list = document.getElementById('comment-panel');
rendered_html = this.renderCommentAppendFromTmall(comment.rateDetail.rateList);
break;
default:
return;
}

list.innerHTML = rendered_html || NOTFOUND;
}.bind(this),
error: function() {
console.log('_fail');
}
});
}.bind(this),
error: function() {
console.log('fail');
}
});
}

可以看到这里嵌套了两个Ajax请求,第一个是获取itemID和sellerID的请求,在获得这两个参数之后,才真正地往刚才我们查询到的URL发送新的请求获取评论内容。

在提取itemID和sellerID时,我先在搜索页面获取到鼠标指向的商品,在触发的popup函数中我从this参数中可以获得href链接,通过这个链接发送Ajax请求获得返回结果之后,采用正则表达式过滤,以上代码中使用的两个正则表达式如下

1
2
this.tmall_itemId_reg = new RegExp("itemId:\"[0,1,2,3,4,5,6,7,8,9]*\"");
this.tmall_sellerId_reg = new RegExp("sellerId:\"[0,1,2,3,4,5,6,7,8,9]*\"");

爬取淘宝的评论

按照和爬取天猫评论同样的思路,爬取淘宝的评论没啥问题,这里不再赘述。

关于’问大家’

当我尝试爬取问大家的内容时,发现请求需要一个Appkey的参数和一个t参数以及一个sign签名参数,不能缺少,却不通用,似乎是随机生成的,而且每次生成的还有时间限制。在这些障碍下,我暂时放弃了这个爬取。

一些问题

现在这个小demo存在两个大问题是
1.搜索结果的第一个商品是无法查询的,因为第一个商品的链接是需要经过一个跳转才能达到目标网页的,本人太懒于是先忽略了。
2.另一个是往下滚动时或者翻页之后,后续加载的商品不能监听到鼠标hover的事件。

源代码的使用

打开chrome的扩展程序页面,勾上开发者模式,点击加载已解压的扩展程序,选中源代码所在的目录即可。

扩展包的安装

将crz后缀的安装包拖入Chrome扩展程序页面即可。

源代码可以在这里下载到

extension-shop-sourcecode.rar


终于更了一篇博文:)