标签:save 对象 attribute 材质 有序字典 red detail 数字 and
前段时间老师让我爬取淘宝的商品列表以及其商品详情数据,期间遇到了很多问题。最困难的就是淘宝的价格数据是以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重命名,否则下一次输出会覆盖前一次的数据。
标签:save 对象 attribute 材质 有序字典 red detail 数字 and
原文地址:http://www.cnblogs.com/f-young/p/7294132.html