前段时间,我家妹子公司老板叫她去将法国亚马逊评论列表的前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个数据需要花费很长的时间才能抓取完,而且抓取了几页或者几十页之后程序就跑不动了,卡住只能关掉再开。当时在没有扩展到抓取中国、美国亚马逊的数据之前,我想到的可能原因有:
- 正则表达式有优化空间,因为我之前没有接触过正则表达式,没有使用过;
- 法国亚马逊网站在国内访问速度慢,影响到了数据的抓取;
- python没有系统的学过,在一些语法或者第三方辅助插件的使用上不够熟悉。
以上三点是我想到的造成抓取效率低下的可能的原因。后来我把同一套代码扩展到抓取中国、美国亚马逊的数据,以验证第二条原因对整个抓取工作的影响程度,结果发现影响非常大!同样的带宽、硬件条件下,中国、美国的前100页共1000个评论用户,抓取大概花了半个多小时,而抓取法国的那1000个数据,花了我近一个下午的时间(因为总是卡住不动,我想应该是urllib打开网页未响应而我的程序没有做判断)才陆陆续续的抓取完,不过也总比妹子一个一个的打开网页再记录下来好,至少人不会烦!然后对中国、美国数据抓取花了半个小时时间,对这个时间花费我个人不好评判是花多了还是说差不多了。但是作为一个开发人员来说,程序总是可以做优化的!
思路:
当时看到网友写的爬虫,思路就是打开网页、匹配自己需要的信息。因此我的思路也是跟着这个来的:通过python的urllib和urllib2插件打开页面,再转换为html数据,利用python的re正则插件去做正则匹配,得到页面、用户详细信息页面、用户联系方式等信息。
具体实现:
if 1 == i: html_link = "http://www.amazon.fr/review/top-reviewers/ref=cm_cr_tr_link_" + str(i); else: html_link = "http://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 = page.read() return html except: print "getHtml2 error"
我使用了try、except就是想看能不能处理打开不开网页的问题(我猜法国亚马逊抓取卡死是因为网站未响应了),但是没有效果;
reg = r'href="(/gp/pdp/profile/.+?)"><b>' captureRe = re.compile(reg) cpList = re.findall(captureRe,html)
b、拼凑链接:
num = (i - 1) * 10 + index; subLink = "http://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 = page.read() return html except: print "getHtml error"
可以看到这个跟前面的那个转换形式不一样,因为我发现利用前一种转换方式得到的页面数据,跟我们之间右键浏览器查看源代码的格式是有差异的,然后我在匹配联系方式的时候一直匹配失败,就以为是这个差异造成的。因此就查找了资料使用了上述形式来转换,网友也说这样能防止亚马逊针对频繁访问的ip做封ip处理;
- 正如我在问题中提到的,抓取效率是一个大问题。1000个数据快都需要花费半个小时才能匹配抓取完,自我感觉效率上还可以提升;
- 在抓取法国亚马逊top-viewer数据的时候,程序一直卡死,但是我不能据此做问题处理,需再查查。