1. 程式人生 > >python 抓取淘寶價格資訊

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不支援中文,還未解決。

最後顯示圖,未儲存。

下一次應該會學習一下如何從網頁上下載圖片。