使用网络爬虫抓取商品价格并分析

需求分析

基于 Chemist Warehouse 的商品, 抓取其每天的价格变化. 并根据历史信息, 判断其价格变化规律, 以便在打折时购买.

因此, 用户需求有如下几点:

  • 抓取网站价格, 需要知道其商品全名, 原价, 打折价, 打折日期, 持续时间
  • 存储这些数据, 供日后分析使用
  • 数据挖掘和分析, 已直观的方式多维度显示出来(譬如单品的打折规律, 打折力度, 打折持续时间. 全年的打折规律)

进一步, 技术分析如下:

  • 全程使用python即可满足全部需求.
  • 网络爬虫难度不高, 仅需针对特定商品, 每天抓一次, 无需多线程/进程, 无需登录, 无验证码, 无需考虑反爬虫, 无需额外加载JS程序.
  • 数据存储, 使用MySQL, 数据需要去重, 仅记录关键信息. 以便减少数据存储量, 简化数据挖掘和分析的工作
  • 搜索指定产品, 展示历史数据, 使用 pyqt + matplotlib.

网络爬虫

花了二天时间, 简单过了一遍网络爬虫的关键技术. 参考资料如下:

本着项目导向, 做出结果为先的思路, 没有一步步的实验. 上来先看了几个爬虫框架.

  • pyspider 基于web UI, 感觉很直观, 适合于随便玩玩. 个人不喜欢, 二次开发不方便.
  • python 下另外一个很有名的框架就是 scrapy, 可惜我连配置安装都没有成功的做完. 适合二次开发.
    应该是公司网络安全机制比较高, 遇到的问题基本都是SSL相关的, 解决了2-3个, 剩下的实在没有思路去解决了…
    另外scrapy依赖的库也比较多, 因此初装也就比较麻烦. 安装推荐参考官网的 Installation guide
  • 使用 requests urllib lxml 库. 简单项目直接用这个就够了.
  • 最终抓数据只用了 lxml 一个库就完成了数据抓取, 去重的工作. 关键源码如下:
# -*- coding:utf-8 -*-
# pip --trusted-host pypi.python.org install lxml

import string
from lxml import html

# 获取url的原始数据
doc = html.parse('http://www.chemistwarehouse.com.au/search?searchtext=blackmores%20bone&searchmode=allwords')
# 获取指定的数据值
names = doc.xpath('//a[@class="product-container search-result"]/@title')
# 处理数据, 准备存入数据库即可.
name = map(string.strip, names)
print name

另:
遇到过了错误 There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED]
使用 pip --trusted-host pypi.python.org install lxml 即可避免. 也是安全性问题导致的.

数据存储

同样地, 该项目对数据存储的要求也很低. 直接选择使用MySQL.

参考资料如下:

Windows 下配置使用MySQL:

  • 下载运行 MySQL Installer

  • 必须安装 MySQL Server. 建议安装 MySQL Workbench, 为可视化图像, 便于管理查看.

  • 可视化工具也可以使用别的软件. 如 heidisql

  • mysql.exe的路径添加PATH环境变量.

  • 创建新的数据库(Workbecn下, 英文为schema), 命名为 chemistwarehouse. 或者输入指令:

    mysql -u root -p      # 登录本机的MySQL数据库服务
    # mysql> # 成功后, 提示符变为 mysql>
    create database chemistwarehouse; # 创建一个数据库
  • 安装 MySQL for Python
    然后, 在python下面测试一下是否可以成功连接到刚建立的 chemistwarehouse 数据库.
    成功的话, 会打印版本信息.

    def initDatabase():
    try:
    # 连接mysql的方法:connect('ip','user','password','dbname')
    connect_db = db.connect(
    'localhost', 'root', 'root', 'chemistwarehouse')
    # 所有的查询,都在连接con的一个模块cursor上面运行的
    cur = connect_db.cursor()
    # 执行一个查询
    cur.execute("SELECT VERSION()")
    # 取得上个查询的结果,是单个结果
    data = cur.fetchone()
    print "Database version : %s " % data
    except Exception as e:
    logging.error(e)
    finally:
    if connect_db:
    # 无论如何,连接记得关闭
    connect_db.close()

    initDatabase()
  • 至此, 就可以在python下正常使用MySQL数据库了.
    将提取出来的数据去重后, 按一定的格式保存进数据库即可.

  • 默认安装在C盘, 而且数据存储也是在C盘. 这个没法接受! 需要把数据存储位置修改到空间更大的E盘.

    • 停止MySQL服务, 命令行 net stop MySQL57 或者使用 MySQL Workbench 停止服务
    • 打开 C:\ProgramData\MySQL\MySQL Server 5.7\my.ini
    • 修改为 datadir=E:/MySQLdata, 即设置数据库的新目录
    • 复制 C:\ProgramData\MySQL\MySQL Server 5.7\Data 下所有文件到 E:/MySQLdata
    • 开启MySQL服务 命令行 net start MySQL57 或者使用 MySQL Workbench 开启服务
    • 检查 MySQL 服务器状态, 确定数据库目录已更新
    • 删除 C:\ProgramData\MySQL\MySQL Server 5.7\Data

数据显示

参考资料如下:

设计思路和注意事项

  • 使用pip安装 matplotlib: pip --trusted-host pypi.python.org install matplotlib
  • 数据显示和数据抓取是完全独立的, 因此数据抓取单独生成了一个exe文件, 数据显示也单独生成一个文件.
  • 数据显示exe可以打开多个, 以便分析比较. 数据抓取仅可打开一个.

源码及性能

最终源码见 github

爬虫最终性能:
抓取效率一般, 每1000条数据大概要2分钟. 要提高效率可以考虑使用多进程!
但一天抓取一次即可, 因此这个速度可以接受. 暂时保持单进程不变.


原创于 DRA&PHO