需求是利用爬蟲抓取店鋪所有商品並下載商品詳細頁所有圖片,隨機挑選店鋪鏈接分析。
但是在實現的過程中遇到各種困難,用selenium,requests利用多種方式都沒有繞過。最後使用淘寶開發者API來實現調取店鋪所有寶貝列表,但是API是付費的,所以在詳細頁使用requests來實現,但是requests僅在抓取天貓商品的時候沒問題,而且我在天貓的詳細頁面抓取的時候使用手機頁面抓取。如:
天貓店鋪所有寶貝清單,也可以用爬蟲實現,以此店鋪鏈接爲例:
所以天貓店鋪的爬蟲實現已經不是問題,代碼也簡單。
1 def get_tmall_taobao_detail(self,iid,category): 2 if category == "tmall": 3 url = "https://detail.m.tmall.com/item.htm?id=%s" % (str(iid)) 4 response = requests.get(url) 5 data = response.content.decode('gbk') 6 re_img_url = re.compile('(https://img.alicdn.com.*?jpg)" src=\"data:image/') 7 alicdn_jpg_list = re_img_url.findall(data) 8 re_title = re.compile(' <title>(.*)</title>') 9 title = re_title.findall(data)[0].replace(".", "-").replace(".", "-") 10 if os.path.isdir("%s%s" % (self.image_path, title)): 11 pass 12 else: 13 os.mkdir("%s%s" % (self.image_path, title)) 14 sum = 1 15 for img in alicdn_jpg_list: 16 jpgname = "詳細頁%s.jpg" %(sum) 17 self.urllib_download(img, title, jpgname) 18 sum = sum + 1
現在問題主要在C店的爬取,C店不管是店鋪信息還是寶貝信息,數據爬取都比較困難。在分析過程中,所有頁面都使用手機終端的請求頭來訪問,並分析相關js和json文件。
找到數據的關鍵鏈接
鏈接在response中看到寶貝的id、title、店鋪寶貝數量等信息,但是鏈接有時效性。
而且C店詳細頁的數據也是一樣,只要突破這個請求,就能實現整個爬蟲,分析URL參數。
經過多次對比分析得到appkey是固定的,t是實時時間戳,sign這個需要計算得到,data中包含了關鍵參數page,shopid,sellerid,所以只要計算sign就可以構建整個url。
在js文件中找到相關計算代碼,其中i是時間戳,g是appkey,c.data是data,d.token需要再尋找
可以看到j需要通過把參數帶入h()函數進行計算返回,j就是sign。sign計算參數只有token未知。
而token來源於cookie中_m_h5_tk前半部分。
現在h()函數中的參數都齊了,單獨摘出h()函數帶入參數計算比對,驗證最後計算與實際sign一致,並且發現這段代碼實際就是md5的計算。
那麼組合各個參數就可以得到sign,然後重組URL就能得到合法請求。
sign_data = self.cookies_m_h5_tk_split + "&" + self.t_now + "&" + self.appkey + "&" + self.get_data self.sign_md5 = hashlib.md5(sign_data.encode(encoding='UTF-8')).hexdigest()
但是,sign會有時間週期,還需要在下一次提示“令牌過期”後重新獲取cookie中的token,然後重新計算sign來提交第二次請求,實現爬蟲,所有寶貝的列表代碼實現如下,同理再實現詳細頁爬蟲部分。
class Get_taobao_detail:
def __init__(self):
self.cookies_m_h5_tk_split = ""
self.appkey = "12574478"
self.get_data = ''
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36"
}
self.cookies = "你的cookie"
self.cookies_dict = {}
for i in self.cookies.split("; "):
self.cookies_dict[i.split("=")[0]] = i.split("=")[1]
self.page_number = 0
self.image_path = "./image/"
self.iid_list = []
self.t_now = str(int(round(time.time() * 1000)))
self.sign_md5 = ""
def response_m_taobao_list(self,shopid,userid,page_number_i):
self.get_data = '{"m":"shopitemsearch","vm":"nw","sversion":"4.6","shopId":"%s","sellerId":"%s","style":"wf","page":%s,"sort":"_coefp","catmap":"","wirelessShopCategoryList":""}' % (shopid,userid,page_number_i)
def get_sign_md5():
sign_data = self.cookies_m_h5_tk_split + "&" + self.t_now + "&" + self.appkey + "&" + self.get_data
self.sign_md5 = hashlib.md5(sign_data.encode(encoding='UTF-8')).hexdigest()
url = "https://h5api.m.taobao.com/h5/mtop.taobao.wsearch.appsearch/1.0/?jsv=2.5.1&appKey=%s&t=%s&sign=%s&api=mtop.taobao.wsearch.appSearch&v=1.0&H5Request=true&AntiCreep=true&type=jsonp&timeout=3000&dataType=jsonp&callback=mtopjsonp8&data=%s" % (
self.appkey, self.t_now, self.sign_md5,self.get_data)
response = requests.get(url, headers=self.headers, cookies=self.cookies_dict)
page_data = response.content.decode('utf-8')
new_cookies = requests.utils.dict_from_cookiejar(response.cookies)
page_number_re = re.compile('pageSize":"(\d+)')
page_number = page_number_re.findall(page_data)
if page_number != []:
self.page_number = int(page_number[0])
return new_cookies, page_data
cookies_pagedata = get_sign_md5()
new_cookies = cookies_pagedata[0]
page_data = cookies_pagedata[1]
if "令牌過期" not in page_data:
return self._re_get_iid(page_data,"taobao")
else:
self.cookies_m_h5_tk_split = new_cookies["_m_h5_tk"].split("_")[0]
self.cookies_dict['_m_h5_tk'] = new_cookies["_m_h5_tk"]
self.cookies_dict['_m_h5_tk_enc'] = new_cookies["_m_h5_tk_enc"]
self.response_m_taobao_list(shopid,userid,page_number_i)
最後效果,可爬取天貓淘寶所有內容: