Python爬虫自学之第(⑤)篇——爬取某宝商品信息
題外話:
《Pi Network 免費挖礦國外熱門項目 一個π幣大約值3元到10元》相信過去BTC的人,信不信未來的PI,了解一下,唯一一個高度與之持平的項目
?
能看到這里說明快進入動態網頁爬取了,在這之前還有一兩個知識點要了解,就如本文要講的json及其數據提取
JSON
是什么
??json是輕量級的文本數據交換格式,符合json的格式的字符串叫json字符串,其格式就像python中字符串化后的字典,有時字典中還雜著列表字典,但是里面的數據都被雙引號包著,下面是一個例子
'{"Africa": [ { "name":"蜜獾" , "nickname":"平頭哥" }, { "name":"蟲子" , "nickname":"小辣條" }, { "name":"毒蛇" , "nickname":"大面筋" }]}'#這是理想化的數據,實際上看到的json是不分行堆在一起,而且更多時候用unicode編碼取代中文而且為了能更好的傳輸各種語言,json對非英語的字符串進行了Unicode編碼,于是我們直接看到的json數據通常都是帶著\uxxxx的字符串而不會帶著中文,json數據還會堆在一起不換行,給我們的分析帶來了困難,不過我們有json 模塊讓它轉回中文,更有一個牛逼工具把它轉回中文同時排版,分析json數據時多用這個工具。
在哪
??有時F12源碼中能看到完整的信息,request回來后就殘缺到沒有價值,這就說明網頁使用了動態或者ajax技術,而這些技術所加載的信息,就有json的身影。為了順利爬取目標,我們需要找到json數據。
- json數據有時會直接出在對原鏈接request的結果中,作為信息等待被加載到網頁中
- 有時會存在于獨立的鏈接里,需要捉包獲取鏈接再打開獲得(而且這種鏈接的構造很重要)
json 模塊
??JSON是JavaScript原生格式,親生無誤,所以在JavaScript中處理JSON數據不需要任何特殊的API或工具包。像python這樣連的遠親,當然不能直接一把捉走別人的孩子,至少要帶根棒棒糖來引誘一下呀,而這根棒棒糖就是json模塊,python自帶。
??json 模塊提供了一種很簡單的方式來編碼和解碼JSON數據,實現了JSON數據(字符串)和python對象(字典)的相互轉換。
主要兩個方法及常用參數:
- json.dumps(obj,ensure_ascii=True): 將一個字典(obj)轉換為JSON編碼的字符串,ensure_ascii默認為True,全部是ascii字符,中文會以unicode編碼形式顯示如\u597d;設置為False時保持中文
- json.loads(s,encoding=): 將一個JSON編碼的字符串(s)轉換回字典,如果傳入的json字符串的編碼不是UTF-8的話,需要用encoding指定字符編碼
如果你要處理的是文件而不是字符串/字典,你可以使用 json.dump() 和 json.load() 來編碼和解碼JSON數據。
# 編碼成json數據寫入,data是字典 with open('data.json', 'w') as f:json.dump(data, f)# 讀取json數據并解碼,data是字典 with open('data.json', 'r') as f:data = json.load(f)另:requests對象的json()方法也可以把json數據轉為字典,dict = r.json(encoding=)
實戰:簡單爬取淘寶商品信息
??爬蟲領域內json的知識知道這些就行,那么馬上來個實戰了解一下怎樣提取json中的數據,加深對json的認識吧,正好可以拿某寶來試手,商品的json數據直接出在對原鏈接request的結果中,不用捉包。(然而大多數json數據不會這樣出現,這里選擇某寶方便展示)
構造鏈接(重要)
重要,但這也是要培養的能力,在這里只詳細講一次思路,以后靠自己分析
??構造鏈接的原則是盡可能多的相關參數,盡可能少的無關參數,網址中?之后用&連起來的賦值關系就是那些參數,這些參數會傳到服務器中,服務器根據它們來返回數據。爬蟲中,頁數,排序,日期等這類的參數是關鍵。我們要動態的修改這些參數來構造鏈接,觀察能力很重要。還有構造鏈接時要多requests下來測試哪些是相關參數,哪些參數是無關緊要的,不是只看瀏覽器就行的
??先進入官網搜索一件商品,這里以GTX2080為例,第一次出現的鏈接如下,
| https://s.taobao.com/search?initiative_id=tbindexz_20170306&ie=utf8&spm=a21bo.2017.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=gtx2080ti&suggest=history_2&_input_charset=utf-8&wq=&suggest_query=&source=suggest |
很長是吧,能大約的看到日期,商品名之類的參數,但是大部分參數都看不懂,我們假設部分參數是不影響爬取結果的,于是我們來繼續按下看看有什么變化,當再次按下搜索鍵
鏈接變短了,在按多幾下都是這個鏈接了
| #初步結構 https://s.taobao.com/search?q=gtx2080ti&imgfile=&js=1&stats_click=search_radio_all%3A1&initiative_id=staobaoz_20200205&ie=utf8 |
為了確保泛用性,我們要多換幾個商品再搜索,確定一下,發現鏈接除q參數(商品名)改變外,其他一模一樣,由此我們初步確定了鏈接結構,q參數是商品名,initiative_id是當天日期,其他不用變
??但我們的還要有翻頁和排序的功能沒實現,鏈接里也看不到和它們有關的參數,因此我們要繼續按來引相關參數出來,點擊排序那排按鈕
發現又多了一個sort參數,不同的排序方式對應不同的值,有default(默認綜合排序),sale-desc(按銷量),renqi-desc(按人氣)等
??按下一頁,又多了bcoffset,p4ppushleft,s三個參數,經測試只有s參數有用,其他兩個都不影響爬取結果(直接去掉),s是頁數相關參數,值是44的倍數(因為每頁加載44件商品),第一頁0,第二頁44,第三頁88……
??到此就捕捉到q,initiative_id,sort,s等參數了,如果想增加其它相關參數,就自己到處按搗鼓吧,下面就這4個參數進行構造,可以format格式化,也可以將參數通過requests.get()的params參數傳入,下面選擇格式化
#使用格式化輸出,傳四個字符串變量進去 |
剩下的就是整合到循環進行多頁爬取了,代碼最后貼上,下面在看看json數據怎樣提取。
json數據分析&提取
先拿一個鏈接requests下來保存到txt看看先,打開后看到一大堆又字典又列表的東西,仔細一看這貨是符合json格式的字符串,里面有我們要的信息。二話不說馬上扔到那個工具里排版一下,排完后如圖
我們知道json數據本質是字符串,也可以用json.load()轉化為字典,這樣的話就有兩種提取信息的方法
- 直接用正則對字符串匹配,缺點是當json存在\uxxxx的unicode編碼時你會得到\uxxxx而不是中文,然而還是有辦法繞過編碼問題——可以通過str(json.load())得到字典(已解碼回中文)后再強轉為字符串再匹配,但是要注意單引號問題
- 轉為字典后逐層索引下去,缺點是當結構過于復雜時,索引也比較麻煩。
?
最終代碼(替換版,使用了selenium模塊)
?
不要看完就算了,記得多實踐,擼起袖子就是干
import time from selenium import webdriver from lxml import htmletree = html.etree# 爬取函數 def start_search_result(keys):# 創建瀏覽器對象browner = webdriver.Chrome()browner.get('https://www.taobao.com/')# 給搜索框賦值kw = browner.find_element_by_id("q") # qkw.send_keys(keys)# 模擬點擊搜索按鈕事件iconfont = browner.find_element_by_class_name('search-button')iconfont.click()# 滑動至瀏覽器下端browner.execute_script("window.scrollTo(0, document.body.scrollHeight);")time.sleep(5)# 獲取網頁源碼html = browner.page_source# 獲取HTML數據html_etree = etree.HTML(html)return html_etree#解析爬取結果函數 def analysis_html(html_etree):print("================================================================")# 獲取商品列表goods_list = html_etree.xpath('//div[@class="items"]/div')# 存儲字典的列表goods_map_list = []for k_value in goods_list:# 獲取圖片地址pic_src = "https:" + k_value.xpath('./div[@class="pic-box J_MouseEneterLeave J_PicBox"]/div[@class="pic-box-inner"]/div[@class="pic"]/a/img/@src',stream=True)[0]# 獲取價格price = "¥" + k_value.xpath('./div[2]/div[1]/div[@class="price g_price g_price-highlight"]/strong/text()',stream=True)[0]# 獲取標題title_list = k_value.xpath('./div[2]/div[2]/a/text()', stream=True)title = "".join(title_list).strip().replace("\n", "")# 獲取店鋪名shop_elem = k_value.xpath('./div[2]/div[3]/div[@class="shop"]/a/text()', stream=True)shop_name = "".join(shop_elem).replace("\n", "").strip()if (len(shop_name) == 0):shop_elem = k_value.xpath('./div[2]/div[3]/div[@class="shop"]/a/span[2]/text()', stream=True)shop_name = "".join(shop_elem).replace("\n", "").strip()infor_map = {}infor_map['pic'] = pic_srcinfor_map['price'] = priceinfor_map['title'] = titleinfor_map['shop'] = shop_namegoods_map_list.append(infor_map)return goods_map_list# 主函數 def main():search_key = input('輸入商品名:\n')print("search_key = ", search_key)# 先獲取爬取的HTML文本html_etree = start_search_result(search_key)# 解析HTML,將商品列表存到list里面goods_list = analysis_html(html_etree)for item in goods_list:print("標題:" + item["title"])print("價格:" + item["price"])print("圖片:" + item["pic"])print("店鋪:" + item["shop"])print('-' * 100)main()效果截圖:
總結
以上是生活随笔為你收集整理的Python爬虫自学之第(⑤)篇——爬取某宝商品信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Makefile教程二 变量
- 下一篇: python处理nc气象数据_气象数据处