python 抓取淘寶價格資訊
接著上一回。
這段程式實現從淘寶主頁開始,輸入搜尋資訊(搜尋‘手錶’),確定搜尋後,爬取結果前20頁所有的價格資訊和地區資訊(其他資訊也可以獲取,暫時只獲取了這兩個),最後用matplotlib繪製了手表價格與數量的頻率圖。
可以看出來,普通手錶價格集中在50-400元左右。
下面介紹程式思路:
思路還是利用selenium模組開啟網頁,返回頁面原始碼,然後利用bs4解析原始碼,獲取資訊。
這次嘗試在selenium庫上載了大跟頭,主要遇到了以下幾個問題
1.跳轉頁面次數不對
一開始利用selenium定位淘寶“下一頁”按鈕,獲取這這一頁資訊後直接跳轉下一頁。結果發現,翻頁的次數總是少於預期的次數。後來經過多次嘗試,發現問題應該是跳轉頁面後元素沒有載入完成,以致無法翻頁。雖然設定了顯示等待,但還是沒有奏效,後來設定了3s的強制等待後,翻頁次數終於達到了預期。
2.跳轉頁面後原始碼未變
好不容易解決了跳轉次數不對的問題,後來發現不管翻了多少頁,打印出來的資訊都是相同的,都是第一頁資訊。也就是說,瀏覽器雖然翻頁過去了,程式獲得的原始碼卻未變。也是搜尋了很多資訊但是一直未解決。有說是因為控制代碼未改(但是我根本不知道控制代碼是啥),而且按照所寫的方法去試了試,還是沒有改變。後來檢索到可能還是頁面還未載入完成,於是,我又強制等待了3s,終於ok。
程式碼:
import time import re from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from bs4 import BeautifulSoup import numpy as np import matplotlib matplotlib.use('TkAgg') import matplotlib.pyplot as plt url = 'https://www.taobao.com' # 淘寶首頁 max_page_account = 20 # 最大頁面數 search_contents = '手錶' # 搜尋內容 # 開啟頁面 browser = webdriver.Chrome() browser.get(url) wait = WebDriverWait(browser, 10) # 價格列表 和 地區列表 price_list = [] location_list = [] def init(): # 等待搜尋框 與 搜尋按鈕 載入完成 input_contents = wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, '#q')) ) bnt_search = wait.until( EC.element_to_be_clickable((By.CSS_SELECTOR, '#J_TSearchForm > div.search-button > button')) ) # 輸入 搜尋內容,點選 搜尋按鈕 input_contents.send_keys(search_contents) bnt_search.click() def next_page(): """翻頁""" # 定位 “下一頁” 按鈕 bnt_next_page = wait.until( EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > ul > li.item.next > a')) ) bnt_next_page.click() time.sleep(5) # 強制等待5s,否則頁面的原始碼不會改變 def get_info(): """獲取資訊""" # 等待 商品列表 載入完成 wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-itemlist > div > div')) ) page = browser.page_source # 獲取原始碼 soup = BeautifulSoup(page, 'html.parser') # 用beautifulsoup解析原始碼 items = soup.find('div', class_='grid g-clearfix') # 獲取商品列表資訊 itemlist = items.find_all('div', class_=re.compile(r'^item J_MouserOnverReq')) for item in itemlist: price = item.find('div', class_='price g_price g_price-highlight').find('strong').get_text() location = item.find('div', class_='location').get_text() price_list.append(float(price)) location_list.append(location) def plot_image(item_list, x_label, y_label): """呼叫獲取資訊函式並繪圖""" count = 0 while count < max_page_account: # 遍歷要求的頁數 count += 1 get_info() time.sleep(5) # 等待5s後再翻頁 if count != max_page_account: next_page() # 繪製頻率圖 plt.hist(item_list, 50, rwidth=0.8) # 這一段註釋在部落格裡單獨解釋 tick = np.linspace(0, 5000, 20) plt.xticks(tick) plt.tick_params(labelsize=6) plt.xlabel(x_label) plt.ylabel(y_label) plt.title(x_label + "-" + y_label) plt.show() init() x_label = "price" y_label = "amount" plot_image(price_list, x_label, y_label)
主要解釋一下繪圖部分程式碼。
在 “#繪製頻率圖”下:
第一行是hist圖,第一個引數是x軸資料列表,這裡即使價格列表;第二個引數是分隔數量,比如手錶價格是200-2000,如果分隔數量是10,那麼每隔區間就是(2000-200)/10,通俗來說就是柱狀圖的數量。第三個引數是柱狀圖的寬度
第2~4行是設定x軸刻度,如果不設定也行,hist圖會預設,但是我覺得刻度不夠精確,重新設定一下。第2行是定義刻度物件,第一個引數是刻度最小值,第二個引數是最大值,第三個引數是間隔數量。第4行是設定x軸刻度字型大小
5~7行是設定x,y軸標籤以及圖題,貌似matplotlib不支援中文,還未解決。
最後顯示圖,未儲存。
下一次應該會學習一下如何從網頁上下載圖片。