返回博客

如何使用 Python 构建价格追踪器进行价格监控

Augustas Pelakauskas

2022-08-121 min read

学习 Python 自动化的一个好办法就是构建一个价格追踪器。对初学者来说,由于这项任务生成的脚本可以立即投入使用,因此尤为方便。

本文将向大家介绍如何用 Python 采集器建立一个可立即实现电商价格监控的可扩展价格追踪器。

价格追踪器是什么?

价格追踪器是一个定期在电商网站上抓取产品价格并提取价格变动的程序。

除了网络抓取这一基本功能外,价格追踪器还配备其他功能,例如当产品价格低于某一阈值时,它就会发出电子邮件提醒。

一个简单的 Python 脚本可用于处理个人任务,而更复杂的价格追踪器则用于追踪数百万种产品的价格。

价格监控的原因

价格监控的好处多多。例如,您可能会以最低价买到一个心仪的产品。

公司则更有充分的理由去监测竞争对手的价格。例如,价格追踪器可以检测竞争对手的销售价格,观察对方何时会对相同的产品展开优惠活动,或为您的产品定一个能实现最佳利润率的价格。价格监控软件可以帮助您恰到好处地调整价格。

搭建 Python 价格监控脚本

本节将展示一个用于追踪多种产品价格的 Python 脚本。我们将使用网络抓取技术来提取产品数据,并自动通过 Python 发送邮件来提醒用户注意价格变动。

项目要求

以下 Python 价格监控脚本适用于 Python 3.6 及以上版本。推荐的库如下所示:

  • Requests:用于发送 HTTP 请求。换句话说,就是在没有浏览器的情况下下载网页。Requests 是后续价格监控脚本的基本库。

  • BeautifulSoup:用于查询 HTML 中的特定元素,封装解析器库。

  • lxml - 用于解析 HTML 文件。Requests 库检索出来的 HTML 是一个字符串,在查询前需要解析成一个 Python 对象。我们不会直接使用这个库,而是使用 BeautifulSoup 来进行封装以获得更直接的 API。

  • 价格解析器:用于每个价格监测脚本的库。它有助于从包含价格的字符串中提取价格。

  • smtplib:用于发送电子邮件。

  • Pandas:用于过滤产品数据和读写 CSV 文件。

此外,您也可以创建一个虚拟环境让整个过程更加有序。

$ python3 -m venv .venv
$ source .venv/bin/activate

打开终端并运行以下命令,安装依赖项:

$ pip install pandas requests beautifulsoup4 price-parser

请注意,smtlib 库属于 Python 标准库,无需单独安装。

安装完成后,创建一个新的 Python 文件并导入以下代码:

import smtplib
import pandas as pd
import requests
from bs4 import BeautifulSoup
from price_parser import Price

此外,添加以下代码用于初始配置:

PRODUCT_URL_CSV = "products.csv"
SAVE_TO_CSV = True
PRICES_CSV = “prices.csv"
SEND_MAIL = True

包含目标 URL 的 CSV 为 PRODUCT_URL_CSV

如果 SAVE_TO_CSV 标志被设置为 True,那么获取的价格将存储在 PRICES_CSV 指定的 CSV 文件中。

SEND_MAIL 是一个标志,可以设置为 True 来发送电子邮件提醒。

读取产品的 URL 列表

存储和管理产品 URL 最简单的办法就是将它们保存在 CSV 或 JSON 文件中。这次使用的是 CSV,便于我们通过文本编辑器或电子表格应用程序进行更新。

CSV 文件应该至少包含两个字段——url  和 alert_price。产品的标题可以从产品的 URL 中提取,也可以存储在同一个 CSV 文件中。如果价格监控器发现产品价格降至低于 alert_price 字段的值,它将触发一个电子邮件提醒。

CSV 中的产品 URL 样本

可以使用 Pandas 读取 CSV 文件并转换为字典对象。接着我们会用一个简单的函数来封装。

def get_urls(csv_file):
    df = pd.read_csv(csv_file)
    return df

该函数将返回一个 Pandas 的 DataFrame 对象,其中包含三栏:产品、URL 和 alert_price(见上图)。

抓取价格

第一步就是在目标 URL 上进行循环。

请注意,get_urls() 返回一个 DataFrame 对象。

首先使用 Pandas 的 to_dict() 方法运行一个循环。当 to_dict 方法在参数为 records 的情况下被调用时,它会将 DataFrame 转换为一个字典列表。

在每个字典上运行一个循环,如下所示:

def process_products(df):
    for product in df.to_dict("records"):
        # product["url"] is the URL

我们将在写完另外两个函数后重新审视这个方法。第一个函数是为了获得 HTML,第二个函数则用于从中提取价格。

运行以下函数,从每个 URL 的响应中获得 HTML:

def get_response(url):
    response = requests.get(url)
    return response.text

接下来,根据响应创建一个 BeautifulSoup 对象,使用 CSS 选择器定位价格元素。使用价格解析器库提取价格浮点,以便与提醒价格进行比较。如果您想深入了解价格解析器库的运行原理,请前往我们的 GitHub 资源库查看示例。

以下函数将从给定的 HTML 中提取价格,并将其作为一个价格浮点返回:

def get_price(html):
    soup = BeautifulSoup(html, "lxml")
    el = soup.select_one(".price_color")
    price = Price.fromstring(el.text)
    return price.amount_float

请注意,本例中使用的 CSS 选择器专门用于抓取目标。如果您正在处理其他网站,这是您唯一要改代码的地方。

在 CSS 选择器的帮助下,我们使用 BeautifulSoup 来定位一个包含价格的元素。该元素存储在 el 变量中。el 标签的文本属性 el.text 包含价格和货币符号。价格解析器会解析这个字符串,然后提取价格的浮点值。

DataFrame 的对象中有一个以上的产品 URL。我们来循环运行所有代码,用新的信息更新 DataFrame。

最简单的方法是将每一行转换成一个字典。这样,您可以读取 URL,调用 get_price() 函数,并更新所需字段。

我们将添加两个新的键值——提取的价格(price)和一个布尔值(alert),用于在发送邮件时过滤函数行。

现在可以扩展 process_products() 函数来演示上述序列:

def process_products(df):
    updated_products = []
     for product in df.to_dict("records"):
        html = get_response(product["url"])
        product["price"] = get_price(html)
        product["alert"] = product["price"] < product["alert_price"]
        updated_products.append(product)
    return pd.DataFrame(updated_products)

这个函数将返回一个新的 DataFrame 对象,包含产品的 URL 和从 CSV 中读取的名称。此外,它还包括用于在价格下降时发送电子邮件的价格和提醒标志。

保存输出

我们只需调用 to_csv() 函数就可以轻松把包含最新产品数据的最终版 DataFrame 保存为 CSV。

此外,我们将检查 SAVE_TO_CSV 标志,如下所示:

if SAVE_TO_CSV:
        df_updated.to_csv(PRICES_CSV, mode="a")

大家可以看到,模式设置为 "a",代表“追加”,确保在 CSV 文件存在的情况下追加新的数据。

发送电子邮件提醒

另外,您可以根据提醒标志,在价格下降时发送电子邮件提醒。首先,创建一个函数,过滤数据框并返回电子邮件的主题和正文。

def get_mail(df):
    subject = "Price Drop Alert"
    body = df[df["alert"]].to_string()
    subject_and_message = f"Subject:{subject}\n\n{body}"
    return subject_and_message

现在,使用 smtplib 创建另一个发送提醒邮件的函数。

def send_mail(df):
    message_text = get_mail(df)
    with smtplib.SMTP("smtp.server.address", 587) as smtp:
        smtp.starttls()
        smtp.login(mail_user, mail_pass)
        smtp.sendmail(mail_user, mail_to, message_text)

这段代码假定您将设置变量 mail_usermail_passmail_to

然后整合一下,这就是主要的功能:

def main():
    df = get_urls(PRODUCT_URL_CSV)
    df_updated = process_products(df)
    if SAVE_TO_CSV:
        df_updated.to_csv(PRICES_CSV, index=False, mode="a")
    if SEND_MAIL:
        send_mail(df_updated)

执行这个函数即可运行整个代码。

如果您想要在特定的时间段内自动运行代码,请在 macOS/Linux 上使用 cronjob,Windows 用户则用 Task Scheduler。

另外,您也可以在云服务环境中部署这个价格监控脚本。

总结

本文展示的 Python 脚本可以从无数产品 URL 中获取产品价格和其他产品数据。该价格监视器的功能可以根据您的偏好进一步扩展。例如,您可以将信息保存到数据库而不是 CSV 中。

如果您准备大规模地运行一个价格监控脚本,那就需要可靠的住宅代理

如需查看完整的代码样本,请参阅我们的 GitHub 资源库。查看网站博客页面,了解更多关于使用 PythonPHPRuby 进行网络抓取的教程或是更详细的操作指南,深入了解如何顺畅地进行网络抓取

关于作者

Augustas Pelakauskas

文案

Augustas Pelakauskas 在 Oxylabs 担任一名文案策划人。拥有艺术家庭背景,他全身心地投入到各种创意项目中 - 最近的他都在写作。验证了他在自由新闻领域的能力后,他转到了科技内容创作。闲暇时,他喜欢阳光明媚的户外活动和运动康乐。事实证明,自行车则是他的第三个好朋友。

Oxylabs博客上的所有信息均按“原样”提供,仅供参考。对于您使用Oxylabs博客中包含的任何信息或其中可能链接的任何第三方网站中包含的任何信息,我们不作任何陈述,亦不承担任何责任。在从事任何类型的抓取活动之前,请咨询您的法律顾问,并仔细阅读特定网站的服务条款或取得抓取许可。

在这篇文章


  • 价格追踪器是什么?

  • 价格监控的原因

  • 搭建 Python 价格监控脚本

  • 总结

选择Oxylabs®,业务更上一层楼


隐私政策

oxylabs.cn© 2024 保留所有权利©