------------恢復內容開始------------
一、完整程式碼:
在MOOC課上嵩天老師的課上有一個查詢商品頁面的例項,學習了一下,發現跟著嵩天老師的原始碼已經爬不出來了。這是因為2019年開始淘寶搜尋頁面就必須登入了,所以要爬取商品內容必須登入賬號,具體的header與cookie資訊如下:
cookie登入資訊可以登入淘寶頁面後經過在元素控制檯內部查詢。(記得重新整理)
先給出完整程式碼
import requests import re def getHTMLText(url): try: header = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36', 'cookie': '_samesite_flag_=t*********************kmn' } r = requests.get(url, timeout=30, headers=header) 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("1312") def printGoodsList(ilt): tplt = "{:4}\t{:8}\t{:16}" print(tplt.format("序號","價格","商品名稱")) count = 0 for g in ilt: count = count + 1 print(tplt.format(count,g[0],g[1])) def main(): goods = '手錶' depth = 2 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()
二、程式碼解析:
總共把程式碼分為三個部分:
1、獲取商品頁面資訊==》getHTMLText
2、解析商品頁面資訊==》parsePage
3、列印商品資訊 ==》printGoodsList
(一)、getHTMLText
def getHTMLText(url): try: header = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36', 'cookie': '_samesite_flag_=t*********************kmn' } r = requests.get(url, timeout=30, headers=header) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except: return ""
1. 首先定義header部分,登入資訊與瀏覽器資訊等。
2. r.raise_for_status() 當爬取失敗的時候會報錯,讓try進入except,使程式碼整體健壯。
3. r.encoding = r.apparent_encoding解析程式碼編碼,讓r資源的編碼 = 顯示的編碼apparent_encoding
4. 最終返回r.text 文字部分
(二)、parsePage
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("")
這個部分是程式碼最關鍵的部分,即核心程式碼,負責查詢與解析r.text中的文字。
先說明其中的正規表示式
r'\"view_price\"\:\"[\d\.]*\"'
在淘寶搜尋書包之後可以發現其商品價格前面的都有一個關鍵詞 view_price,同理發現商品標題都有raw_title關鍵詞:
其中\"view_price\"\:\"[\d\.]*\"之所以出現這麼多\,是因為轉義字元其意義是 查詢"view_price: [\d.]*"這樣的一個字串,使用findall函式可以爬取全部的資源。
同理,經過商品標題可以選擇title與raw_title不過最後選擇了raw_title,因為title在一個商品資訊內出現了兩次。
最終plt 與 tlt 分別是所有商品資訊的價格和標題,其序號是一一對應的。
for i in range(len(plt)): price = eval(plt[i].split(':')[1]) title = eval(tlt[i].split(':')[1]) ilt.append([price, title])
最終把所有商品資訊的價格和名稱放入列表ilt內
這plt去除外面的雙引號後使用SPLIT方法吧view_price:129這樣的商品元素分開,並取位置[ 1 ]上的元素,即商品的價格。
三、商品價格資訊列印:printGoodsList
def printGoodsList(ilt): tplt = "{:4}\t{:8}\t{:16}" print(tplt.format("序號","價格","商品名稱")) count = 0 for g in ilt: count = count + 1 print(tplt.format(count,g[0],g[1]))
先定義TPLT格式資訊,最後使用count計數當做序號。
四、main()函式執行
def main(): goods = '手錶' depth = 2 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)
根據查詢淘寶頁面的url我們可以發現其搜尋的介面為 search?q=
並且其頁面元素為44位一頁,第一頁為空 第二頁為44 第三頁為88
所以根據查詢多少我們可以定義一個深度depth為查詢的頁面,遍歷次數即每一次翻頁的次數。
https://s.taobao.com/search?q=%E4%B9%A6%E5%8C%85&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=6&ntoffset=6&p4ppushleft=1%2C48&s=0 https://s.taobao.com/search?q=%E4%B9%A6%E5%8C%85&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=3&ntoffset=3&p4ppushleft=1%2C48&s=44 https://s.taobao.com/search?q=%E4%B9%A6%E5%8C%85&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&bcoffset=3&ntoffset=0&p4ppushleft=1%2C48&s=88
最終執行結果為: