前段時間,我家妹子公司老板叫她去將法國亞馬遜評論列表的前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數據的時候,程序一直卡死,但是我不能據此做問題處理,需再查查。