第二個例子是使用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}\t{:8}\t{: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()