第二个例子是使用requests库+re库爬取淘宝搜索商品页面的商品信息
(1)分析网页源码
打开淘宝,输入关键字“python”,然后搜索,显示如下搜索结果
从url连接中可以得到搜索商品的关键字是“q=”,所以我们要用的起始url为:https://s.taobao.com/search?q=python
然后翻页,先跳到第二页,url变为:
再跳到第三页,url变为:
经过对比发现,翻页后,变化的关键字是s,每次翻页,s便以44的倍数增长(可以数一下每页显示的商品数量,刚好是44)
所以可以根据关键字“s=”,来设置爬取的深度(爬取多少页)
右键查看源码:
分析商品名称和商品价格分别由哪个关键字控制:
商品名称可能的关键字是“title”和“raw_title”,进一步多看几个商品的名称,发现选取“raw_title”比较合适;商品价格自然就是“view_price”(通过比对淘宝商品展示页面);
所以商品名称和商品价格分别是以 "raw_title":"名称" 和 "view_price":"价格",这样的键/值对的形式展示的。
(2)分析如何实现
与上一个例子爬取“最好大学排名”不同,淘宝商品信息不像之前的大学信息是以HTML格式嵌入的,这里的商品信息并未以HTML标签的形式处理数据,而是直接以脚本语言放进来的,所以不需要用BeautifulSoup来解析,直接用正则表达式提取 关键字信息即可
(3)提取信息
写个demo,看看是如何一步步解析信息的
# coding:utf-8 import requests import re goods = '水杯' url = 'https://s.taobao.com/search?q=' + goods r = requests.get(url=url, timeout=10) html = r.text tlist = re.findall(r'"raw_title":".*?"', html) # 正则提取商品名称 plist = re.findall(r'"view_price":"[d.]*"', html) # 正则提示商品价格 print(tlist) print(plist) print(type(plist)) # 正则表达式提取出的商品名称和商品价格都是以列表形式存储数据的
去掉列表中的键,只留下值,也就是去掉每组数据的“raw_title”和“view_price”
print('第一个商品的键值对信息:', tlist[0]) # 查看第一个商品的键值对信息 a = tlist[0].split(':')[1] # 使用split()方法以":"为切割点,将商品的键值分开,提取值,即商品名称 print('第一个商品的名称', a) print(type(a)) # 查看a的类型 b = eval(a) # 使用eval()函数,去掉字符串的引号 print('把商品名称去掉引号后', b) # 查看去掉引号后的效果 print(type(b)) # 查看b的类型
利用for循环,把每个商品的名称和价格组成一个列表,然后把这写列表再追加到一个大列表中:
goodlist = [] for i in range(len(tlist)): title = eval(tlist[i].split(':')[1]) # eval()函数简单说就是用于去掉字符串的引号 price = eval(plist[i].split(':')[1]) goodlist.append([title, price]) # 把每个商品的名称和价格组成一个小列表,然后把所有商品组成的列表追加到一个大列表中 print(goodlist)
完整代码:
# coding: utf-8 import requests import re # def getHTMLText(url): # try: # r = requests.get(url, timeout=30) # r.raise_for_status() # r.encoding = r.apparent_encoding # return r.text # except: # return "" # # # def parsePage(ilt, html): # try: # plt = re.findall(r'"view_price":"[d.]*"', html) # tlt = re.findall(r'"raw_title":".*?"', html) # for i in range(len(plt)): # price = eval(plt[i].split(':')[1]) # title = eval(tlt[i].split(':')[1]) # ilt.append([price, title]) # except: # print() # # # def printGoodsList(ilt): # tplt = "{:4} {:8} {:16}" # print(tplt.format("序号", "价格", "商品名称")) # count = 0 # for t in ilt: # count = count + 1 # print(tplt.format(count, t[0], t[1])) # # # def main(): # goods = '高达' # depth = 3 # start_url = 'https://s.taobao.com/search?q=' + goods # infoList = [] # for i in range(depth): # try: # url = start_url + '&s=' + str(44 * i) # html = getHTMLText(url) # parsePage(infoList, html) # except: # continue # printGoodsList(infoList) # # # main() def get_html(url): """获取源码html""" try: r = requests.get(url=url, timeout=10) r.encoding = r.apparent_encoding return r.text except: print("获取失败") def get_data(html, goodlist): """使用re库解析商品名称和价格 tlist:商品名称列表 plist:商品价格列表""" tlist = re.findall(r'"raw_title":".*?"', html) plist = re.findall(r'"view_price":"[d.]*"', html) for i in range(len(tlist)): title = eval(tlist[i].split(':')[1]) # eval()函数简单说就是用于去掉字符串的引号 price = eval(plist[i].split(':')[1]) goodlist.append([title, price]) def write_data(list, num): # with open('E:/Crawler/case/taob2.txt', 'a') as data: # print(list, file=data) for i in range(num): # num控制把爬取到的商品写进多少到文本中 u = list[i] with open('E:/Crawler/case/taob.txt', 'a') as data: print(u, file=data) def main(): goods = '水杯' depth = 3 # 定义爬取深度,即翻页处理 start_url = 'https://s.taobao.com/search?q=' + goods infoList = [] for i in range(depth): try: url = start_url + '&s=' + str(44 * i) # 因为淘宝显示每页44个商品,第一页i=0,一次递增 html = get_html(url) get_data(html, infoList) except: continue write_data(infoList, len(infoList)) if __name__ == '__main__': main()