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不支持中文,还未解决。

最后显示图,未保存。


下一次应该会学习一下如何从网页上下载图片。

没有更多推荐了,返回首页