從零開始寫Python爬蟲 --- 爬蟲應用:一號店 商品信息查詢程序
這次我們來爬取電商信息,還是那句話,爬蟲抓下來的數據一定要有意義才行,
至於為什麼要抓電商,我才不會告訴你我想搶一部魅藍note6呢
成果展示:
這次相當於將爬蟲寫成了一個隨時可以用的小腳本,
先來看一下最終的結果:思路分析
先來看一下項目結構
.n├── __pycache__n│ ├── citydict.cpython-36.pycn│ └── spider.cpython-36.pycn├── citydict.py # 靜態資源文件 城市id 省份idn├── cityid.html # 用於解析城市id的一號店網頁部分內容n├── handler.py # 程序的主要入口<提供基礎的用戶交互>n├── spider.py # 爬虫部分n└── tools.py # 解析數據的部分n1 directory, 7 filesn
經過了這麼長時間的寫爬蟲經驗
我們對一些網站的基本數據分布也有了自己的感覺就比如說電商的數據一般情況下都是ajax動態生成的所以想要直接用requests抓取頁面解析是行不通的,我們來試試看打開一個一號店商品的頁面:
http://item.yhd.com/item/76716479打開chrome開發者工具
發現我們想要的數據
果然是通過ajax的方式渲染到頁面上的有很多啦:* 價格* 是否可以銷售* 是否顯示* 庫存* 本地庫存* 銷售數量* ....一號店雞賊的地方在於:
他居然不把數據放在chr界面,而是放在了一個動態的js文件中可叫我一頓好找來分析一下這個ajax請求
這是一個GET下來的文本數據(居然不用json)
請求頭中我們需要注意的就是:- request url
- 請求參數
mcsite:1 # 必填參數nprovinceId:3 # 省份idncityId:23 # 城市idncountyId:252 # 國家idnpmId:76716479 # 商品idnruleType:2 # 商品規則nbusinessTagId:16 # 還沒弄清楚ncallback:jQuery111305397697550805665_1504256542202 # 回掉參數 大概是unix時間戳的某種變形n_:1504256542203n
到這裡我們的思路就清楚了:
- 構造符合要求的request url
- 解析數據
經過我的嘗試,我發現最後的回調參數是可以不清求的,估計一號店那裡還沒有開啟相關的驗證
請求參數的獲取:
pmId: 我們很容易就能從url鏈接里獲取
provinceId、cityId :這兩個明顯是一個靜態的資源,我們只需要找到提供對應關係的字典/json文件就能找到對應的關係了可是我在資源文件里找了好久,
都沒有找到相關的文件這讓我有點灰心啊,後來一想,反轉這個文件只需要解析一次我直接從網頁的數據里解析不也一樣嘛?於是乎我就截取了部分一號店首頁的html源碼解析出了我想要的數據
我們來整理一下思路
- 接受用戶輸入的商品名
- 通過搜索解析出商品id
- 通過本地文件的城市省份id表構造ajax請求
- 解析ajax返回的數據並展示
代碼展示
城市省份id解析部分
n解析1號店的所有n省份n城市信息nnimport osnfrom bs4 import BeautifulSoupnn# 獲取當前運行目錄npath = os.path.dirname(os.path.abspath(__file__))nnwith open(path + /cityid.html) as f:n html = f.read()nndef get_cityid_map(html):n n 解析一號店省份、城市idn return <dict>n n cityid_map = {}n soup = BeautifulSoup(html, lxml)n # 找到所有的a標籤n citys = soup.find_all(a)n # 開始解析城市名城市id 省份idn for city in citys:n name = city.text.replace(市,)n provinceId = city[data-provinceid]n cityid = city[data-cityid]n cityid_map[name] = {provinceId: provinceId, cityid: cityid, }nn return cityid_mapn
關鍵的爬虫部分
import requestsnfrom bs4 import BeautifulSoupnnndef get_html_text(url):n n 返回網頁textn n try:n r = requests.get(url, timeout=30)n r.raise_for_status()n r.encoding = r.apparent_encodingn return r.textn except:n raise ValueError(errors)nnndef parse_good_detail(pmId, provinceId=5, cityid=37):n n 查詢指定id商品的庫存和價格n 默認查詢 江蘇省 南京市 的庫存n n # 一號點的Ajax伺服器請求地址n # 默認使用江蘇省為省份信息n url = http://gps.yhd.com/restful/detail?mcsite=1&provinceId={}&cityId={}&pmId={}&ruleType=2&businessTagId=16.format(n provinceId, cityid, pmId)n text = get_html_text(url)n # 對信息進行初步格式化 刪掉data無用信息n content = text[text.find({) + 1:-2]n data_dict = {}n # 將所有的類json數據格式化存入字典n for rec in content.split(,):n data_dict[rec.split(":")[0].replace(n ", ).replace(", )] = rec.split(:)[1]nn # 查找我們想要的信息n price = data_dict[currentPrice]n stock = data_dict[currentStockNum]nn return price, stocknnndef parse_goods_info(url,provinceId=5, cityid=37):n n 抓取指定url的所有商品的nn 商品idn 價格n 庫存n 鏈接nn returen: goods_infolist<dict in list>n nn goods_infolist = []nn html = get_html_text(url)n soup = BeautifulSoup(html, lxml)n # 找到所有商品的a標籤n goods_list = soup.find_all(a, class_=mainTitle)nn for good in goods_list:n url = good[href][2:]n title = .join(good[title].split( )[:3]) # 對標題稍微格式化一下n pmId = good[pmid]n try:n price, stock = parse_good_detail(pmId,provinceId,cityid)n except:n price, stock = 信息錯誤, 信息錯誤n goods_infolist.append(n {name: title, price: price, stock: stock, url: url})nn return goods_infolistn
用戶交互的部分
# 導入城市省份資源文件nfrom citydict import CITY_MAPnn# 導入爬蟲程序nfrom spider import parse_goods_infonimport timenndef main():n good = input(請輸入需要查詢的商品:t)n city = input(請輸入查詢城市:t)n provinceId = CITY_MAP[city][provinceId]n cityid = CITY_MAP[city][cityid]n # 構造商品搜索的鏈接n searc_url = http://search.yhd.com/c0-0/k + goodn print(正在搜索相關商品)n # 調用我們寫的爬蟲抓取數據n res = parse_goods_info(searc_url, provinceId, cityid)n print(搜索完畢.....正在處理數據)n # 格式化輸出一下n for rec in res:n print(型號: {}t價格: {}t庫存: {}t地址: {}.format(n rec[name], rec[price], rec[stock], rec[url]))n time.sleep(0.5)nnif __name__ == __main__:n main()n
總結
本次爬蟲的難度不大,
但是卻是一個十分有用的程序我來假設一個使用場景:
我炒雞想要某個商品,可是這部商品坑爹要搶購
我怎麼樣才能第一時間知道這個商品補貨/上架的時間呢?
用這個腳本 定時循環爬取,一旦庫存>0 我們就給用戶發送通知~當然,我也只是想想,畢竟有貨了我也買不起 (逃~)
每天的學習記錄都會 同步更新到:
微信公眾號: findyourownway知乎專欄:https://zhuanlan.zhihu.com/Ehco-pythonblog : www.ehcoblog.mlGithub: https://github.com/Ehco1996/Python-crawler推薦閱讀:
※伊朗是威脅海灣國家安全的罪魁禍首?海灣民眾:我們不信
※參加POINT.數據分析師特訓營(北京)是什麼體驗?
※如何在Excel合理分配圖表的坐標軸?
※[原]深入對比數據科學工具箱:Python和R之爭
※數據查詢,網站在手人無你有