從零開始寫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抓取頁面解析

是行不通的,我們來試試看

打開一個一號店商品的頁面:

item.yhd.com/item/76716

打開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

知乎專欄:zhuanlan.zhihu.com/Ehco

blog : www.ehcoblog.ml

Github: github.com/Ehco1996/Pyt

推薦閱讀:

伊朗是威脅海灣國家安全的罪魁禍首?海灣民眾:我們不信
參加POINT.數據分析師特訓營(北京)是什麼體驗?
如何在Excel合理分配圖表的坐標軸?
[原]深入對比數據科學工具箱:Python和R之爭
數據查詢,網站在手人無你有

TAG:爬虫 | Python | 数据 |