利⽤Python抓取亚马逊评论列表数据
  前段时间,我家妹⼦公司⽼板叫她去将法国亚马逊评论列表的前100页共1000个评论⽤户的联系⽅式出来。1000个⽤户,要⼀个个的去看再记录下来,⽽且并不是每个评论⽤户都会将个⼈的联系⽅式留下来。那么问题来了,这样费时费⼒的⼯作如果⼈⼯去做的话,那么就是花了两天的时间也就了前30页的数据(还有别的⼯作要做),然后累的够呛的。本着⼼疼的原则(程序猿能到妹⼦就很不错了,所以得⼼疼着),就想帮着她做点事。
  我本⾝的⼯作是做游戏客户端开发的,主要使⽤的开发语⾔是lua和c++,并没有接触过⽹页、⽹站相关的⼯作。只是⼯作中有⽤到过python脚本,然后有⼀次在⽹上查python的相关资料的时候,有看到⽹友⽤python写爬⾍⼲点事的。所以我就想,我是否也能够实⽤python 来写爬⾍去亚马逊的⽹站抓取数据呢?就这样现学现⽤的开始敲起代码来了。
环境:
  windows7
  python:2.7
利⽤的python插件:
  urllib2、urllib插件,⽤了打开⽹页链接;
  re插件,⽤来做正则匹配;
  codecs插件,⽤来做编码转换及数据保存。
⽬前实现的功能:
  抓取法国亚马逊top-viewer列表前100页共1000个⽤户的姓名、联系⽅式(⽹站链接或者邮箱)、国籍(可能有卢森堡、瑞⼠的买家在法国亚马逊购买)、⽤户评论详细页⾯的链接等数据。
  通过抓取法国亚马逊top-viewer列表数据,进⽽扩展到抓取中国亚马逊、美国亚马逊top-viewer列表的数据。理论上通过简单的修改可以抓取不同国家亚马逊top-viewer列表的数据。
需改进的地⽅:
  代码写好之后,抓取数据的过程中发现效率好低,1000个数据需要花费很长的时间才能抓取完,⽽且抓取了⼏页或者⼏⼗页之后程序就跑不动了,卡住只能关掉再开。当时在没有扩展到抓取中国、美国亚马逊的数据之前,我想到的可能原因有:
1. 正则表达式有优化空间,因为我之前没有接触过正则表达式,没有使⽤过;
2. 法国亚马逊⽹站在国内访问速度慢,影响到了数据的抓取;
3. python没有系统的学过,在⼀些语法或者第三⽅辅助插件的使⽤上不够熟悉。
  以上三点是我想到的造成抓取效率低下的可能的原因。后来我把同⼀套代码扩展到抓取中国、美国亚马逊的数据,以验证第⼆条原因对整个抓取⼯作的影响程度,结果发现影响⾮常⼤!同样的带宽、硬件条件下,中国、美国的前100页共1000个评论⽤户,抓取⼤概花了半个多⼩时,⽽抓取法国的那1000个数据,花了我近⼀个下午的时间(因为总是卡住不动,我想应该是urllib打开⽹页未响应⽽我的程序没有做判断)才陆陆续续的抓取完,不过也总⽐妹⼦⼀个⼀个的打开⽹页再记录下来好,⾄少⼈不会烦!然后对中国、美国数据抓取花了半个⼩时时间,对这个时间花费我个⼈不好评判是花多了还是说差不多了。但是作为⼀个开发⼈员来说,程序总是可以做优化的!
思路:
  当时看到⽹友写的爬⾍,思路就是打开⽹页、匹配⾃⼰需要的信息。因此我的思路也是跟着这个来的:通过python的urllib和urllib2插件打开页⾯,再转换为html数据,利⽤python的re正则插件去做正则匹配,得到页⾯、⽤户详细信息页⾯、⽤户联系⽅式等信息。
具体实现:
1、法国亚马逊的top评论列表⼤概有1000个⽹页,每个页⾯有10个⽤户数据。每个页⾯,除了第⼀页的链接外,其它页⾯的链接都跟页⾯数相关,如 是代表23页的数据,因此可以通过简单的字符串拼接就可以得到1000个页⾯的页⾯链接了。这是关于得到各个页⾯链接的⽅法;⽰例代码如下:
a、拼接页⾯链接,因为第⼀页和其余页的格式稍微有点不同,所以分开来处理:
if 1 == i:
html_link = "www.amazon.fr/review/top-reviewers/ref=cm_cr_tr_link_" + str(i);
else:
html_link = "www.amazon.fr/review/top-reviewers/ref=cm_cr_tr_link_" + str(i) + "?ie=UTF8&page=" + str(i);
b、将页⾯转为html:
try:
page = urllib.urlopen(url)
html = ad()正则匹配链接
return html
except:
print"getHtml2 error"
我使⽤了try、except就是想看能不能处理打开不开⽹页的问题(我猜法国亚马逊抓取卡死是因为⽹站未响应了),但是没有效果;
2、每个页⾯有10个⽤户的数据,点开⼀个⽤户会跳转到其详细信息页⾯,通过查看不同详细信息页⾯的链接形式,发现都是类似的:⼀个可能是⽤户名的变量,⼀个表⽰该⽤户在评论列表中的排名值。因此我可以想办法得到⽤户名(猜想是⽤户名、或者是亚马逊保存的⼀个唯⼀标⽰)、⽤户在评论列表中的排名,然后拼接出⽤户详细信息页⾯的链接;通过查看页⾯的源码,发现每个页⾯中,⽤户信息的形式类似,都是诸如:/gp/pdp/profile/xxxx/这样的形式,因此可以通过简单的正则匹配得到xxxx这个数据,暂且称为⽤户唯⼀标⽰符。这是关于得到详细页⾯链接的⽅法;⽰例代码:
a、匹配每个⽤户的唯⼀标⽰符:
reg = r'href="(/gp/pdp/profile/.+?)"><b>'
captureRe = repile(reg)
cpList = re.findall(captureRe,html)
b、拼凑链接:
num = (i - 1) * 10 + index;
subLink = "www.amazon.fr" + cp + "/ref=cm_cr_tr_tbl_" + str(num) + "_name";
index指的是10个数据中具体哪个,num其实就是⽤户在评论列表中的排名,⼀页10个,所以能根据页码及index来算出具体的排名;
c、转为html:
headers = { #伪装为浏览器抓取
'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
}
req = urllib2.Request(url,headers=headers)
page = "";
try:
page = urllib2.urlopen(req)
html = ad()
return html
except:
print"getHtml error"
可以看到这个跟前⾯的那个转换形式不⼀样,因为我发现利⽤前⼀种转换⽅式得到的页⾯数据,跟我们之间右键浏览器查看源代码的格式是有差异的,然后我在匹配联系⽅式的时候⼀直匹配失败,就以为是这个差异造成的。因此就查了资料使⽤了上述形式来转换,⽹友也说这样能防⽌亚马逊针对频繁访问的ip做封ip处理;
3、不是每个评论者都提供了联系⽅式,但是提供了联系⽅式的只有两种形式:⼀个⽹站链接(博客或者啥);⼀个邮箱。通过查看源码发现:提供⽹站链接的,在源码中会有⼀个nofollow标签,⽽提供邮箱的则有⼀个mailto:关键词。有了这两个信息,那么我就可以据此来做正则匹配了。这就是关于得到联系⽅式的⽅法。这⾥也是两个正则表达式做正则匹配,跟上述代码类似就不上代码了;
4、后⾯⼜通过正则匹配得到了评论⼈姓名、国籍等信息。操作也跟3中提到的类似。
缺陷:
1. 正如我在问题中提到的,抓取效率是⼀个⼤问题。1000个数据快都需要花费半个⼩时才能匹配抓取完,⾃我感觉效率上还可以提升;
2. 在抓取法国亚马逊top-viewer数据的时候,程序⼀直卡死,但是我不能据此做问题处理,需再查查。
写在最后:
  这个⼩脚本⼤概花了⼀个下午的时间才折腾出来,然后⼜花了些时间去满⾜妹⼦提的其他需求,第⼆天才把最终抓取到的数据发送给妹⼦使⽤。但总的来说,⽐起妹⼦可能要花1个礼拜才能做完,我也是帮了点⼩忙了。⽽我⾃⼰本⾝也学到了东西:数据抓取!虽然我这只是简单得不能再简单的⼀种实现,但是也相当于稍微⼊了门,积累了点知识!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。