作為一個剛入門的電商小白,淘寶網頁上存在著大量數據,對于一位數據分析師來說,有著極大的誘惑力。本篇文章將應用以往幾篇文章的理論基礎靜態網頁的爬取思路,實戰爬取淘寶商品數據。
01 明確目標
我們打開淘寶網站頁面:。本次爬取目標是通過關鍵字搜索得到的商品數據,以“短袖”為例,如下圖。
我們在網頁上看到能獲取的商品數據有:價格、是否包郵、付款人數、商品名稱、店鋪地址、店鋪名稱等變量。本次爬取目標為獲取多頁商品數據信息。
02 梳理思路
在開始實際操作之前,梳理邏輯是最為重要的,特別是對于比較復雜的網址爬取。首先使用瀏覽器,右鍵 “檢查” 進入開發者編輯模式,這時在選項卡可以看到網頁的源代碼(和右鍵查看網頁源代碼一樣),大部分網站的網頁信息都可以在網頁源代碼里找到并爬取下來,我們將這些網站稱之為靜態網站。如何判斷一個網站是否為靜態網站,我們可以通過是否能夠將信息從網頁源代碼里爬取下來判斷。
此時我們在網頁源代碼中找到了商品名稱,意味著只需要將這部分網頁源代碼爬取下來,就能夠得到第一頁數據。
我們已經梳理完爬取一頁的信息,那么如何實現多頁爬取呢?
此時就需要去解析網址,發現網址翻頁間的變化規律。小白直接截取了四頁的網址信息,
第一頁:https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=%E7%9F%AD%E8%A2%96&suggest=history_1&_input_charset=utf-8&wq=&suggest_query=&source=suggest
第二頁:https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=%E7%9F%AD%E8%A2%96&suggest=history_1&_input_charset=utf-8&wq=&suggest_query=&source=suggest&bcoffset=3&ntoffset=3&p4ppushleft=1%2C48&s=44
第三頁:https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=%E7%9F%AD%E8%A2%96&suggest=history_1&_input_charset=utf-8&wq=&suggest_query=&source=suggest&bcoffset=0&ntoffset=6&p4ppushleft=1%2C48&s=88
第四頁:https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=%E7%9F%AD%E8%A2%96&suggest=history_1&_input_charset=utf-8&wq=&suggest_query=&source=suggest&bcoffset=-3&ntoffset=-3&p4ppushleft=1%2C48&s=132
發現從第二個網址開始多了4個變量,而最后一個變量s為等差數列,結合網頁顯示的商品個數,發現從第二頁開始每一頁商品數量剛好為44個,翻頁主要依靠s這個變量掌控,因此推測出第一頁S=0。理完爬蟲思路,趕緊開始正式爬取吧!
03 代碼實現
由于淘寶的反爬蟲機制,我們需要在中獲取瀏覽器的請求信息靜態網頁的爬取思路,我們點擊DOC模塊(即:文件),該模塊下存放著該網址的請求信息以及響應信息,如下圖。
可以看到,請求方式為GET請求,同時摘取和兩個最重要的偽裝瀏覽器變量,同時加入參數用來設置服務器響應時間,防止請求超時。
import re
import requests
headers={'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
'referer': 'https://www.taobao.com/',
'cookie': 't=67d5e6f261229e537cb23f43ba5709a7; cna=yoSJFOZGjFYCAdy/BFy08waT; thw=cn; ali_ab=220.184.205.111.1553926930230.1; tg=0; hng=CN%7Czh-CN%7CCNY%7C156; _cc_=WqG3DMC9EA%3D%3D; uc3=id2=&nk2=&lg2=; tracknick=; enc=3kARZ%2FPMmoftPzxcaXjPgwjPTGP%2FmrrgeZVhCOpVkvv%2Fn1rOCA7B4DOdJnytruMCDM9FCj66Oxq1QRRuCgaHkg%3D%3D; cookie2=18e0f07baf4fd6e3052d92d17f62d760; _tb_token_=e3339eebe87f3; x=2001220798; uc1=cookie14=UoTZ4Mn%2F3%2FaA0Q%3D%3D&lng=zh_CN; skt=851bcba5615eb169; csg=2ac64eee; v=0; alitrackid=www.taobao.com; lastalitrackid=www.taobao.com; _m_h5_tk=378e05eb59e54de4e6181ff7b6ff7284_1554653316840; _m_h5_tk_enc=3a3bac4d04609984a12cb3bb75aa0581; JSESSIONID=83CB3150D9EB0A85F9CFEA6B5A0AD284; l=bBIfuI8rv29ReknSBOCiquI-7F7OSIRAguPRwshvi_5Ca6L_EebOlGSyXFp6Vj5Rs0LB402lRpJ9-etki; isg=BI-P0zhADyxhXQvlm4OxATv_HiNZHJ6jJ3h9d6GcK_4FcK9yqYRzJo1iduDrCLtO'}
url='https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=%E7%9F%AD%E8%A2%96&suggest=history_1&_input_charset=utf-8&wq=&suggest_query=&source=suggest&bcoffset=-3&ntoffset=-3&p4ppushleft=1%2C48&s=0'
res=requests.get(url,headers=headers,timeout=10)
res.text
輸出結果中我們已經可以找到第一頁的商品信息,現在需要將有用的信息提取出來,直接在DOC模塊下找打該網址,并點擊模塊通過crtl+F查找商品名稱,根據查找到的值,我們發現這部分信息存儲在一個json中,json的數據格式很有規律,由字典嵌套構成,我們只需編寫正則json提取并用切片提取即可。
data=re.findall('g_page_config =(.*?)g_srp_loadCss.*',res.text,re.S)
注意:使用re.S可以實現換行匹配。正則文章鏈接
將正則匹配的數據進行清洗成json所需格式,通過中的json模塊直接將其轉化為json。接下來就是從json中提取數據并存儲,代碼如下:
price=[]
name=[]
address=[]
count=[]
title=[]
id_=[]
detail_url=[]
for item in cont['mods']['itemlist']['data']['auctions']:
name.append(item['nick'])
price.append(item['view_price'])
address.append(item['item_loc'])
count.append(item['view_sales'].replace('人收貨',''))
title.append(item['raw_title'])
id_.append(item['nid'])
detail_url.append(item['detail_url'])
result={'店鋪名稱':name,'商品標題':title,'價格':price,'店鋪地址':address,'銷量':count,'商品編號':id_,'詳情頁網址':detail_url}
results=pd.DataFrame(result)
第一頁的信息爬取完成,翻頁爬取即構造網址使用一個for循環即可。
url_1='https://s.taobao.com/search?q=%E7%9F%AD%E8%A2%96&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=6&ntoffset=6&p4ppushleft=1%2C48&s={}'
for i in range(10):
url=url_1.format(i)
res=requests.get(url,headers=headers,timeout=10)
04 總結與反思
本篇主要對于淘寶商品進行簡單的數據爬取,通過和來模擬瀏覽器行為,并沒有采取報錯處理措施,適合小規模的數據爬取。往后會寫一些應對反爬措施、爬蟲效率以及動態網頁爬取的東西。
反思:如果未加,會一直報錯,一般爬取淘寶使用賬號登入后的比較穩定,此點也可以延伸到通過爬蟲模擬登入淘寶從而自動獲取進行數據爬取,但由于淘寶登入機制太過復雜,投入產出比很低,因此建議大家直接復制即可;當連續爬了幾頁后報錯時,大多是過期了,刷新頁面并重新獲取一份即可。
如果有對爬蟲和數據分析感興趣的同學記得隨手點個關注喲~~~
最后附上完整代碼~
import re
import requests
import pandas as pd
import json
#?headers和cookies、url都需要手動設置為自己瀏覽器的信息
headers={'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
'referer': 'https://www.taobao.com/',
'cookie': 't=67d5e6f261229e537cb23f43ba5709a7; cna=yoSJFOZGjFYCAdy/BFy08waT; thw=cn; ali_ab=220.184.205.111.1553926930230.1; tg=0; hng=CN%7Czh-CN%7CCNY%7C156; _m_h5_tk=378e05eb59e54de4e6181ff7b6ff7284_1554653316840; _m_h5_tk_enc=3a3bac4d04609984a12cb3bb75aa0581; _cc_=UIHiLt3xSw%3D%3D; x=2001220798%26e%3D1%26p%3D*%26s%3D0%26c%3D0%26f%3D0%26g%3D0%26t%3D0%26__ll%3D-1%26_ato%3D0; enc=9uN%2B1ywqiZPxTCxyN8zzj9BGdrNa7VS4au9XGDMcvONK6Cmx8hGCKVAm5YYaDgjpWmCDw%2FsmLF13%2BgCbhi40uQ%3D%3D; cookie2=1e9202e02371e03ed8a1e7af945b72ef; _tb_token_=e487373334d5b; mt=ci=0_0; v=0; alitrackid=www.taobao.com; lastalitrackid=www.taobao.com; JSESSIONID=36C6071F00102D714774721EC911738A; l=bBIfuI8rv29ReJ4SBOfgZuI-7F7tgKAfhVVzw41AzIB19U5aidBcjHwprIz2L3Q_E_5Lzetrq8bBLRFkJra_Wx1..; isg=BBISzgQvmgY3HOZOBpTEmi4AY9g0i2vIEleQXNxjK0Z077XpxLPezw9NXwv2oY5V'}
url_1='https://s.taobao.com/search?q=%E7%9F%AD%E8%A2%96&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=6&ntoffset=6&p4ppushleft=1%2C48&s={}'
price=[]
name=[]
address=[]
count=[]
title=[]
id_=[]
detail_url=[]
sale=[]
for i in range(10):
url=url_1.format(i)
res=requests.get(url,headers=headers,timeout=10)
data=re.findall('g_page_config =(.*?)g_srp_loadCss',res.text,re.S)
cont=json.loads(data[0].strip()[:-1])
for item in cont['mods']['itemlist']['data']['auctions']:
name.append(item['nick'])
price.append(item['view_price'])
address.append(item['item_loc'])
count.append(item['view_sales'].replace('人收貨',''))
title.append(item['raw_title'])
id_.append(item['nid'])
detail_url.append(item['detail_url'])
print('第'+str(i)+'頁爬取完成')
result={'店鋪名稱':name,'商品標題':title,'價格':price,'店鋪地址':address,'銷量':count,'商品編號':id_,'詳情頁網址':detail_url}
results=pd.DataFrame(result)