1. 程式人生 > >淘寶商品列表以及商品詳情數據抓取

淘寶商品列表以及商品詳情數據抓取

文本 def 銷量 .com [1] 寫入excel d+ pan bind

前段時間老師讓我爬取淘寶的商品列表以及其商品詳情數據,期間遇到了很多問題。最困難的就是淘寶的價格數據是以Ajax異步加載的,這些數據暫時還沒有能力獲取到。

下面介紹一下基本思路。

首先,通過抓取商品列表的商品ID獲取商品的身份標識,然後根據商品ID跳轉到具體的商品列表,對其他屬性進行抓取。

觀察兩條商品列表的URL:

https://s.taobao.com/search?q=帽子&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.50862.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170806&bcoffset=7&ntoffset=7&p4ppushleft=1%2C48&s=0

https://s.taobao.com/search?q=帽子&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.50862.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170806&bcoffset=4&ntoffset=4&p4ppushleft=1%2C48&s=44

https://s.taobao.com/search?q=帽子&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.50862.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170806&bcoffset=4&ntoffset=4&p4ppushleft=1%2C48&s=88

這是前三個頁面的URL,可以發現,除了"q="和"s="後面的數據不一樣,其他的都是一樣的,因此,可以把URL簡化為:

https://s.taobao.com/search?q=keyword&s=pagenum

其中,q代表搜索的關鍵詞,s代表商品列表的頁數,0代表第一頁,44代表第二頁,88代表第三頁……

先以此URL抓取商品的ID等信息。

代碼如下。

import re
import requests
from pandas import *
from collections import OrderedDict
def getDetails(startpage,endpage):
	#如果需要爬取具體的商品詳情,頁數過多可能會出現異常,此函數可以用來控制一次爬取的頁數
	url_head=‘https://s.taobao.com/search?q=帽子&s=‘   
	#這是淘寶搜索列表的url前面的相同部分,q=‘‘代表搜索的關鍵詞,s=‘‘代表第幾頁,s=0為第1頁s=44為第二頁,以此類推

	url_list=[url_head+str(i*44) for i in range(startpage-1,endpage)]  #生成需要爬取的商品列表url

	#定義存儲商品列表數據數據的列表
	nid_list=[]
	raw_title_list=[]
	view_price_list=[]
	view_sales_list=[]
	item_loc_list=[]
	for url in url_list:
	    resp=requests.get(url)
	    print(resp.url)
	    nid=re.findall(pattern=‘"nid":"(.*?)"‘,string=resp.text)  #商品id,唯一,可以此跳轉到其商品詳情頁面,然後進行其他信息的抓取
	    raw_title=re.findall(pattern=‘"raw_title":"(.*?)"‘,string=resp.text)  #商品名稱
	    view_price=re.findall(pattern=‘"view_price":"(.*?)"‘,string=resp.text)  #商品價格
	    view_sales=re.findall(pattern=‘"view_sales":"(.*?)"‘,string=resp.text)  #商品銷量
	    item_loc=re.findall(pattern=‘"item_loc":"(.*?)"‘,string=resp.text)  #發貨地址

	    #逐個存儲
	    nid_list.extend(nid)
	    raw_title_list.extend(raw_title)
	    view_price_list.extend(view_price)
	    view_sales_list.extend(view_sales)
	    item_loc_list.extend(item_loc)

    #生成數據框
	dt={‘商品id‘:nid_list,‘商品名稱‘:raw_title_list,‘商品價格‘:view_price_list,
					‘商品銷量‘:view_sales_list,‘商品發貨地址‘:item_loc_list}

	df=DataFrame(dt)  #根據字典生成數據框
	#寫入Excel
	writer1=ExcelWriter("taobao_details.xlsx")  #新建一個空白Excel工作簿
	df.to_excel(writer1,"Sheet1")  #將df寫入Sheet1工作表
	writer1.save()

  

  上述代碼可以獲取到商品ID、商品名稱、商品價格、商品銷量、發貨地址信息。接下來,利用商品ID信息,跳轉到具體的商品詳情頁面,對其他屬性進行抓取。

對其他屬性的抓取,主要著眼於兩個方面。一個是商品的描述、服務於物流評分,這個雖然淘寶與天貓的HTML頁面有所差別,但是獲取方式大同小異。另外,所有的商品詳情都放在了一個列表裏面,因此用beautifulsoup提取十分方便。

抓取淘寶商品詳情的代碼如下:

def getTaoBaoDetails(url):
	import requests
	import re
	from bs4 import BeautifulSoup
	# from pandas import DataFrame
	from collections import OrderedDict
	res=requests.get(url)
	soup=BeautifulSoup(res.text,"html.parser")
	
	dd=soup.select(".tb-shop-rate dd") #獲取描述、服務、物流的數字信息,該信息存放在一個列表,需要使用正則表達式提取
	dd_value=[]
	if len(dd)>0:
		try:
			for d in range(0,3):
				dd_value.append(re.search(pattern=r‘[\s]*([0-9]\.[0-9])[\s]*‘,string=dd[d].text).group(1))
		except IndexError as err:
			print(res.url)
	#下面的語句獲取屬性列表
	attrs=soup.select(".attributes-list li")
	attrs_name=[]
	attrs_value=[]
	for attr in attrs:
		attrs_name.append(re.search(r‘(.*?):[\s]*(.*)‘,attr.text).group(1))
		attrs_value.append(re.search(r‘(.*?):[\s]*(.*)‘,attr.text).group(2))

	allattrs=OrderedDict() #存放該產品詳情頁面所具有的屬性
	for k in range(0,len(attrs_name)):
		allattrs[attrs_name[k]]=attrs_value[k]

	info=OrderedDict()  #存放該商品所具有的全部信息
	#下面三條語句獲取描述、服務、物流的評分信息
	if len(dd_value)>0:
		info[‘描述‘]=dd_value[0]
		info[‘服務‘]=dd_value[1]
		info[‘物流‘]=dd_value[2]
	else:
		info[‘描述‘]=‘NA‘
		info[‘服務‘]=‘NA‘
		info[‘物流‘]=‘NA‘

	#下面的語句用來判斷該商品具有哪些屬性,如果具有該屬性,將屬性值插入有序字典,否則,該屬性值為空
	#適用場景
	if ‘適用場景‘ in attrs_name:
		info[‘適用場景‘]=allattrs[‘適用場景‘]
	else:
		info[‘適用場景‘]=‘NA‘
	#適用對象
	if ‘適用對象‘ in attrs_name:
		info[‘適用對象‘]=allattrs[‘適用對象‘]
	else:
		info[‘適用對象‘]=‘NA‘
	#款式
	if ‘款式‘ in attrs_name:
		info[‘款式‘]=allattrs[‘款式‘]
	else:
		info[‘款式‘]=‘NA‘
	#尺碼
	if ‘尺碼‘ in attrs_name:
		info[‘尺碼‘]=allattrs[‘尺碼‘]
	else:
		info[‘尺碼‘]=‘NA‘
	#帽頂款式
	if ‘帽頂款式‘ in attrs_name:
		info[‘帽頂款式‘]=allattrs[‘帽頂款式‘]
	else:
		info[‘帽頂款式‘]=‘NA‘
	#帽檐款式
	if ‘帽檐款式‘ in attrs_name:
		info[‘帽檐款式‘]=allattrs[‘帽檐款式‘]
	else:
		info[‘帽檐款式‘]=‘NA‘
	#檐形
	if ‘檐形‘ in attrs_name:
		info[‘檐形‘]=allattrs[‘檐形‘]
	else:
		info[‘檐形‘]=‘NA‘
	#主要材質
	if ‘主要材質‘ in attrs_name:
		info[‘主要材質‘]=allattrs[‘主要材質‘]
	else:
		info[‘主要材質‘]=‘NA‘
	#人群
	if ‘人群‘ in attrs_name:
		info[‘人群‘]=allattrs[‘人群‘]
	else:
		info[‘人群‘]=‘NA‘
	#品牌
	if ‘品牌‘ in attrs_name:
		info[‘品牌‘]=allattrs[‘品牌‘]
	else:
		info[‘品牌‘]=‘NA‘
	#風格
	if ‘風格‘ in attrs_name:
		info[‘風格‘]=allattrs[‘風格‘]
	else:
		info[‘風格‘]=‘NA‘
	#款式細節
	if ‘款式細節‘ in attrs_name:
		info[‘款式細節‘]=allattrs[‘款式細節‘]
	else:
		info[‘款式細節‘]=‘NA‘
	#顏色分類
	if ‘顏色分類‘ in attrs_name:
		info[‘顏色分類‘]=allattrs[‘顏色分類‘]
	else:
		info[‘顏色分類‘]=‘NA‘
	#適用季節
	if ‘適用季節‘ in attrs_name:
		info[‘適用季節‘]=allattrs[‘適用季節‘]
	else:
		info[‘適用季節‘]=‘NA‘
	#適用年齡
	if ‘適用年齡‘ in attrs_name:
		info[‘適用年齡‘]=allattrs[‘適用年齡‘]
	else:
		info[‘適用年齡‘]=‘NA‘

	return info

  抓取天貓商品詳情的代碼如下:

def getTmallDetails(url):
	import requests
	import re
	from bs4 import BeautifulSoup
	# from pandas import DataFrame
	from collections import OrderedDict
	res=requests.get(url)
	soup=BeautifulSoup(res.text,"html.parser")
	# dt=soup.select(".tb-shop-rate dt") #獲取描述、服務、物流的文本信息,該信息存放在一個列表,需要使用正則表達式提取
	dd=soup.select(".shop-rate ul li") #獲取描述、服務、物流的數字信息,該信息存放在一個列表,需要使用正則表達式提取
	# dt_name=[]
	dd_value=[]
	# for t in range(0,3):
	# 	dt_name.append(dt[t].text)
	if len(dd)>0:
		for d in dd:
			dd_value.append(re.search(r‘([0-9][.][0-9])‘,d.text).group())
	#下面的語句獲取屬性列表
	attrs=soup.select(‘#J_AttrUL li‘)
	attrs_name=[]
	attrs_value=[]
	for attr in attrs:
		attrs_name.append(re.search(r‘(.*?):[\s]*(.*)‘,attr.text).group(1))
		attrs_value.append(re.search(r‘(.*?):[\s]*(.*)‘,attr.text).group(2))

	allattrs=OrderedDict() #存放該產品詳情頁面所具有的屬性
	for k in range(0,len(attrs_name)):
		allattrs[attrs_name[k]]=attrs_value[k]

	info=OrderedDict()  #存放該商品所具有的全部信息
	#下面三條語句獲取描述、服務、物流的評分信息
	if len(dd_value)>0:
		info[‘描述‘]=dd_value[0]
		info[‘服務‘]=dd_value[1]
		info[‘物流‘]=dd_value[2]
	else:
		info[‘描述‘]=‘NA‘
		info[‘服務‘]=‘NA‘
		info[‘物流‘]=‘NA‘
	#下面的語句用來判斷該商品具有哪些屬性,如果具有該屬性,將屬性值插入有序字典,否則,該屬性值為空
	#適用場景
	if ‘適用場景‘ in attrs_name:
		info[‘適用場景‘]=allattrs[‘適用場景‘]
	else:
		info[‘適用場景‘]=‘NA‘
	#適用對象
	if ‘適用對象‘ in attrs_name:
		info[‘適用對象‘]=allattrs[‘適用對象‘]
	else:
		info[‘適用對象‘]=‘NA‘
	#款式
	if ‘款式‘ in attrs_name:
		info[‘款式‘]=allattrs[‘款式‘]
	else:
		info[‘款式‘]=‘NA‘
	#尺碼
	if ‘尺碼‘ in attrs_name:
		info[‘尺碼‘]=allattrs[‘尺碼‘]
	else:
		info[‘尺碼‘]=‘NA‘
	#帽頂款式
	if ‘帽頂款式‘ in attrs_name:
		info[‘帽頂款式‘]=allattrs[‘帽頂款式‘]
	else:
		info[‘帽頂款式‘]=‘NA‘
	#帽檐款式
	if ‘帽檐款式‘ in attrs_name:
		info[‘帽檐款式‘]=allattrs[‘帽檐款式‘]
	else:
		info[‘帽檐款式‘]=‘NA‘
	#檐形
	if ‘檐形‘ in attrs_name:
		info[‘檐形‘]=allattrs[‘檐形‘]
	else:
		info[‘檐形‘]=‘NA‘
	#主要材質
	if ‘主要材質‘ in attrs_name:
		info[‘主要材質‘]=allattrs[‘主要材質‘]
	else:
		info[‘主要材質‘]=‘NA‘
	#人群
	if ‘人群‘ in attrs_name:
		info[‘人群‘]=allattrs[‘人群‘]
	else:
		info[‘人群‘]=‘NA‘
	#品牌
	if ‘品牌‘ in attrs_name:
		info[‘品牌‘]=allattrs[‘品牌‘]
	else:
		info[‘品牌‘]=‘NA‘
	#風格
	if ‘風格‘ in attrs_name:
		info[‘風格‘]=allattrs[‘風格‘]
	else:
		info[‘風格‘]=‘NA‘
	#款式細節
	if ‘款式細節‘ in attrs_name:
		info[‘款式細節‘]=allattrs[‘款式細節‘]
	else:
		info[‘款式細節‘]=‘NA‘
	#顏色分類
	if ‘顏色分類‘ in attrs_name:
		info[‘顏色分類‘]=allattrs[‘顏色分類‘]
	else:
		info[‘顏色分類‘]=‘NA‘
	#適用季節
	if ‘適用季節‘ in attrs_name:
		info[‘適用季節‘]=allattrs[‘適用季節‘]
	else:
		info[‘適用季節‘]=‘NA‘
	#適用年齡
	if ‘適用年齡‘ in attrs_name:
		info[‘適用年齡‘]=allattrs[‘適用年齡‘]
	else:
		info[‘適用年齡‘]=‘NA‘

	return info

  最後,將所獲取的信息合並在一起,輸出為Excel:

url_start=‘https://item.taobao.com/item.htm?id=‘
	info_df=DataFrame()
	for id in nid_list:
		url_detail=url_start+str(id)
		res=requests.get(url_detail)
		if not isnull(re.search(‘tmall‘,res.url)):
			detial=getTmallDetails(url_detail)
		else:
			detial=getTaoBaoDetails(url_detail)
		detial[‘商品id‘]=id
		info_df=info_df.append(detial,ignore_index=True)
	writer2=ExcelWriter("detail.xlsx")
	info_df.to_excel(writer2,"Sheet1")
	writer2.save()

  上述代碼應該與第一部分的代碼合並在一起,這樣會同時輸出兩個Excel,如果每10個頁面輸出一次,則需要對輸出的Excel重命名,否則下一次輸出會覆蓋前一次的數據。

淘寶商品列表以及商品詳情數據抓取