1. 程式人生 > >爬取淘寶商品資訊

爬取淘寶商品資訊

我們先來解決一下前置知識,本爬蟲會用到以下庫

  1. requests 是一個很實用Python的一個很實用的HTTP客戶端,可以滿足如今爬蟲的需要
  2. json 用於資料的處理
  3. csv 用於資料的儲存

分析說明

爬取淘寶商品的資訊,資料主要用於分析市場趨勢,從而制定一系列營銷方案。實現功能如下:

  1. 使用者提供關鍵字,利用淘寶搜尋功能獲取搜尋後的資料
  2. 獲取商品資訊:標題,價格,銷量,店鋪所在區域
  3. 資料以檔案格式儲存

功能實現依次體現了爬蟲的開發流程:爬蟲規則->資料清洗->資料儲存。

使用谷歌瀏覽器進入淘寶網站,利用搜索的功能輸入‘四件套’關鍵字,
使用瀏覽器的除錯功能捕捉資訊,如果在響應的HTML中找不到資料,
那麼可能資料是通過Ajax請求後臺的,再通過前端渲染到頁面上去的,
單擊XHR,傳送一個請求,檢視資料請求資訊如下圖所示

接下來,我們單擊Preview檢視該URL的響應資料格式,
發現數據是JSON格式的,商品的標題,價格,銷量,店鋪名稱和店鋪所在地點
分別對應的資料為raw_title,view_price,view_sales,nick,item_loc

我們把它的請求連結拿出來研究一下

https://s.taobao.com/api?_ksTS=1540176287763_226&callback=jsonp227&ajax=true&m=customized&sourceId=tb.index&_input_charset=utf-8&bcoffset=-1&commend=all&suggest=history_1&source=suggest&search_type=item&ssid=s5-e&suggest_query=&spm=a21bo.2017.201856-taobao-item.2&q=四件套&s=36&initiative_id=tbindexz_20170306&imgfile=&wq=&ie=utf8&rn=9e6055e3af9ce03b743aa131279aacfd

請求連結的資料

我們可以把這個長長的連結簡化一下

https://s.taobao.com/api?callback=jsonp227&m=customized&q=%E5%9B%9B%E4%BB%B6%E5%A5%97&s=36

從簡化後的URL看出,有兩個引數可以動態設定來獲取不同的商品

  1. q = 四件套 這個是搜尋的關鍵字
  2. s = 36 這個是頁數設定,

功能實現

根據對網站的分析獲取單個關鍵字搜尋的單頁商品資訊,程式碼如下:

import requests
import json
url = "https://s.taobao.com/api?callback=jsonp227&m=customized&q=四件套&s=36"
r = requests.get(url)
response = r.text
# 擷取成標準的JSON格式
# 由於Ajax返回的資料是字串格式的餓,在返回的值jsonp227(XXX)中
# XXX部分是JSON格式資料,因此先用字串split()擷取XXX部分,
#然後將XXX部分由字串格式轉成JSON格式的資料讀取
response = response.split('(')[1].split(')')[0]
# 讀取JSON
response_dict = json.loads(response)
# 定位到商品資訊列表
response_auctions_info = response_dict['API.CustomizedApi']['itemlist']['auctions']

如果想要獲取多頁資料,可以在上述的程式碼中加入一個迴圈,實現程式碼如下:

for p in range(88):
	url = "https://s.taobao.com/api?callback=jsonp227&m=customized&q=四件套&s=%s" % (p)
	r = requests.get(url)
	# 獲取響應資訊字串
	response = r.text
	# 轉換成JSON格式
	response = response.split('(')[1].split(')')[0]
	# 載入資料
	response_dict = json.loads(response)
	# 商品資訊
	response_auctions_info = response_dict['API.CustomizedApi']['itemlist']['auctions']

上述程式碼只能獲取單個關鍵字搜尋的商品資訊,
如果要實現多個關鍵字的功能呢,就可以在上述程式碼中在多加一個迴圈,程式碼如下:

for k in ['四件套','手機殼']:
for p in range(88):
	url = "https://s.taobao.com/api?callback=jsonp227&m=customized&q=%s&s=%s" % (k,p)
	r = requests.get(url)
	response = r.text
	response = response.split('(')[1].split(')')[0]
	response_dict = json.loads(response)
	# 商品資訊
	response_auctions_info = response_dict['API.CustomizedApi']['itemlist']['auctions']

資料儲存

我們以CSV檔案的格式儲存資料,我們來定義一個函式:

def get_auctions_info(response_auctions_info,file_name):
	with open(file_name,'a',newline='') as csvfile:
		# 生成CSV物件,用於寫入CSV檔案
		writer = csv.writer(csvfile)
		for i in response_auctions_info:
			# 判斷是否資料已經記錄
			if str(i['raw_title']) not in auctions_distinct:
				# 寫入資料
				# 分別是商品資訊列表和CSV檔案路徑。
				# 但該檔案並沒有對CSV設定表頭,所以在開始獲取資料之前。
				# 應該生成對應CSV檔案,並設定其表頭
				writer.writerrow([i['raw_title'],i['view_price'],i['view_sales'],i['nick'],i['item_loc']])

				auctions_distinct.append(str(i['raw_title']))
		csvfile.close()

綜合上述條件,整體程式碼如下:

import requests
import json
import csv
# 定義全域性變數,用於判斷資料是否已經記錄
global auctions_distinct
auctions_distinct = []

def get_auctions_info(response_auctions_info, file_name):
    with open(file_name, 'a', newline='') as csvfile:
        # 生成csv物件,用於寫入CSV檔案
        writer = csv.writer(csvfile)
        for i in response_auctions_info:
            # 判斷是否資料已經記錄
            if str(i['raw_title']) not in auctions_distinct:
                # 寫入資料
                writer.writerow([i['raw_title'], i['view_price'],i['view_sales'], i['nick'], i['item_loc']])
                auctions_distinct.append(str(i['raw_title']))
        csvfile.close()

if __name__ == '__main__':
    for k in ['四件套', '手機殼']:
        # 新建csv檔案,每迴圈一個關鍵字會生成其對應的CSV檔案
        file_name = k + '.csv'
        with open(file_name, 'w', newline='') as csvfile:
            writer = csv.writer(csvfile)
            # 寫入表頭資訊
            writer.writerow(['標題', '價格', '銷量', '店鋪', '區域'])
			# 寫完關閉檔案
            csvfile.close()
        # 迴圈次數可以根據實際自行設定
        for p in range(88):
            url = 'https://s.taobao.com/api?callback=jsonp227&m=customized&q=%s&s=%s' % (k, p)
            r = requests.get(url)
            response = r.text
            response = response.split('(')[1].split(')')[0]
            response_dict = json.loads(response)
            response_auctions_info = response_dict['API.CustomizedApi']['itemlist']['auctions']
            # 呼叫函式get_auctions_info寫入商品資訊
            get_auctions_info(response_auctions_info, file_name)
    print('獲取資料量為:' + len(auctions_distinct))

總結

  1. 去除無用的連結的引數,簡化連結
  2. 分析URL的請求引數含義以及響應內容的資料規律
  3. 資料儲存的去重判斷