使用Python实现网站监控,赋予实时洞察力

介绍

本项目的目的是开发一个Python程序,自动化监测和跟踪多个网站的变化过程。我们旨在通过利用Python简化检测和记录基于Web的内容修改的繁琐任务。这种能力对于实时新闻追踪、即时产品更新和进行竞争分析非常宝贵。随着数字领域的快速发展,识别网站变化对于保持持续的意识和理解至关重要。

学习目标

我们在这个项目中的学习目标将涵盖以下组成部分:

  1. 增强使用Python库(如BeautifulSoup和Scrapy)进行网络爬虫的方法知识。我们旨在高效地从网站中提取有价值的数据,导航HTML结构,识别特定元素,并处理不同的内容类型。
  2. 提高识别网站内容微小变化的技能。我们希望学习比较新抓取的数据与现有参考数据的技术,以检测插入、删除或修改。我们还计划处理在这些比较过程中遇到的各种数据格式和结构。
  3. 利用Python的自动化能力跟踪网站更新。我们计划使用cron作业或Python的调度库等调度机制,以增强数据收集并消除重复任务。
  4. 全面了解HTML的架构。我们旨在熟练地导航HTML文档,识别在数据提取过程中至关重要的元素,并有效地处理网站布局和结构的变化。
  5. 通过探索数据处理技术来提高文本处理能力。我们将学习清洁和精炼提取的数据,解决数据编码复杂性,并操纵数据进行深入分析和多功能报告。

本文是数据科学博客马拉松的一部分。

项目描述

本项目旨在设计一个Python应用程序,监控和记录选择网站的变化。该应用程序将包括以下内容:

  1. 网站检查:对指定网站进行持续评估,以发现特定内容或部分的更新。
  2. 数据获取:使用网络爬虫方法从网站中提取所需的详细信息,如文本、图形或相关数据。
  3. 变化识别:将新抓取的数据与先前存储的数据进行对比,以发现差异或修改。
  4. 通知机制:实现一个警报机制,当发现变化时向用户发送通知。
  5. 日志记录:详细记录随时间的修改,包括时间戳和有关变化的信息。该应用程序可以根据用户的偏好监视任何给定的网站和特定内容。预期的结果包括关于网站变化的即时警报和全面的变化记录,以了解变化的性质和时间。

问题陈述

本项目的主要目标是简化对特定网站的监控过程。通过创建一个Python应用程序,我们计划跟踪和记录感兴趣网站上的变化。这个工具将及时更新最新新闻文章、产品列表和其他基于Web的内容的修改。自动化这个跟踪过程将节省时间,并确保对网站进行的任何修改或添加的即时了解。

方法

为了成功实施这个项目,我们将遵循以下高级步骤:

  1. 我们的项目将使用Python强大的库,如BeautifulSoup或Scrapy。这些库使从网站收集信息和筛选HTML内容变得容易。
  2. 我们将从网站获取信息,以在开始时创建一个基准。这个基准数据将帮助我们在以后识别任何变化。
  3. 我们可以将输入数据与一组基准进行匹配,以跟踪任何新添加或更改。我们的技术可能涉及文本比较或分析HTML结构的差异。
  4. 我们将通过日志文件跟踪项目的运行。这些日志将包含有用的细节,如运行时间、跟踪的网站和找到的变化。它们将帮助我们跟踪更新并找到模式。
  5. 作为系统的一部分,将集成一个通知功能。如果检测到变化,将通过电子邮件、短信或其他方法发送警报,实时向用户更新。

场景

想象一家从各个网站收集儿童活动信息并整合到自己的网站上的公司。然而,手动跟踪每个网站的变化并相应地更新自己的平台带来了重大挑战。这就是我们专门的工具发挥作用的地方,为克服这些障碍提供了高效的解决方案。

监控的网站示例:

我们监控各种网站,整理儿童活动信息。以下是一些示例:

超级顶级网球

该组织提供课程、夏令营和派对等吸引人的项目,向2至7岁的孩子们介绍网球世界。他们的重点是教授网球基础知识,促进健康和协调性,并培养良好的体育精神。

下一步百老汇

这所位于泽西城的表演艺术学校提供优质的舞蹈、声乐和表演课程。他们迎合各种技能水平的学生,在支持和鼓舞人心的环境中培养他们的创造力和自信。

尼姆布斯学校

这所在泽西城声名显赫的机构为各个年龄段和技能水平的人们提供舞蹈教育。凭借多样的舞蹈流派和举办演出和社区外展项目,他们为当地艺术场景作出贡献,并培养对舞蹈的欣赏。

我们开发了一个基于Python的解决方案,利用网络爬虫技术自动化这个过程。我们的工具定期监控所选网站,检测儿童活动信息的变化。一旦发现变化,工具会无缝地更新公司的网站,始终反映最新的信息。

除了更新网站,我们的工具还会保持详细的变更日志,为分析和参考提供有价值的数据。它还可以配置为发送实时通知,让公司的团队了解到任何检测到的变化。利用我们的工具可以使公司简化运营,确保其网站始终展示来自多个来源的最新信息。

关于网络爬虫的警告

需要注意的是,网络爬虫活动可能涉及法律和伦理问题。在进行任何爬取活动之前,必须验证目标网站是否允许爬取,或者从网站所有者获取必要的许可。遵守网站的服务条款并尊重其政策至关重要。此外,需要注意请求频率,并避免可能干扰网站运营的做法。始终谨慎处理网络爬虫,并遵循最佳实践,以确保良好和合规的体验。

采用复杂的方法从目标网站的主页提取页面链接。下面是一个代码片段,我们将使用Python的BeautifulSoup库从超级顶级网球的主页提取页面链接:

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
import pandas as pd

# 主页的URL
url = 'https://www.superdupertennis.com/'

# 通过GET请求获取HTML内容
response = requests.get(url)
html_content = response.text

# 使用BeautifulSoup解析HTML内容
soup = BeautifulSoup(html_content, 'html.parser')

# 从锚标签(<a>)中提取页面链接
links = soup.find_all('a')

# 创建一个列表来存储数据
data = []
for link in links:
    page_name = link.text.strip()  
    # 去除前导/尾随空格 
    # 并正确格式化页面名称
    web_link = link.get('href')  
    # 使用get()方法获取 
    #'href'属性的值
    if web_link:  # 在添加到表格之前检查 
    #'href'属性是否存在
        complete_link = urljoin(url, web_link)  
        # 使用urljoin构建完整的网页链接
        data.append({
            '服务提供商': '超级顶级网球',  
            # 根据实际的服务提供商名称进行更新
            '页面名称': page_name,
            '完整的网页链接': complete_link
        })

# 从数据创建一个pandas DataFrame
df = pd.DataFrame(data)
  • 我们引入了requests、BeautifulSoup和pandas等必要的工具库。我们还选择了要探索的网站,例如’https://www.superdupertennis.com/’。
  • 通过requests库向该URL发送GET请求。主页的结果HTML内容将保存在’html_content’中。
  • BeautifulSoup会审查HTML内容并识别'<a>’标签。这些标签通常包含我们感兴趣的链接。
  • 每个'<a>’标签都会被处理,从中提取页面名称和’href’值,即实际链接。我们还通过去除额外的空格来整理提取的数据。
  • 借助urllib.parse中的urljoin()函数,我们将基本URL和每个相对链接结合起来形成完整的URL。
  • 所有清理和准备好的数据都被放入’data’列表中。该列表包含包含服务提供商名称、清理后的页面名称和完整URL的字典。
  • 最后,我们使用pandas将’data’列表转换为DataFrame。该DataFrame分为三列:’服务提供商’、’页面名称’和’完整的网页链接’。

初始数据捕获

为了建立未来比较的基线,通过从网站上爬取所需内容并将其存储在诸如数据库或文件之类的数据结构中来执行初始数据捕获。以下是前面代码的续写:

for a,b,c in zip(df['服务提供商'].to_list(),
df['页面名称'].to_list(),df['网页链接'].to_list()):
    url = c
    headers = {'User-Agent': 'Mozilla/5.0 
    (Macintosh; Intel Mac OS X 10_10_1) 
    AppleWebKit/537.36 (KHTML, like Gecko) 
    Chrome/39.0.2171.95 Safari/537.36'}

    time.sleep(60)
    
    # 下载页面
    response = requests.get(url, headers=headers)
    # 解析下载的首页
    soup = BeautifulSoup(response.text, "lxml")
    
    # 删除脚本和样式
    for script in soup(["script", "style"]):
        script.extract() 
    soup = soup.get_text()
    
    current_ver = soup.splitlines()
    with open(r"路径\{}\{}\{}_{}_{}.txt".
    format(a,b,a,b,date.today().strftime
    ('%Y-%m-%d')),"a",encoding="utf-8") as file:
        file.write("\n".join(current_ver))
    
    file.close()

使用pandas DataFrame,我们迭代行以访问服务提供商、页面名称和网页链接。这些变量分别赋值给a、b和c。

我们在迭代中将url变量设置为网页链接(c)。此外,我们为requests库定义headers变量。

为了在请求之间引入合理的延迟,我们使用time.sleep()函数暂停60秒。

接下来,我们发送GET请求,使用指定的URL和headers下载页面的内容。响应存储在response变量中。

使用基于”lxml”解析器的BeautifulSoup,我们解析下载的首页并提取文本内容。从解析内容中删除脚本和样式。

提取的文本按行分割并赋值给current_ver变量。

最后,我们以写入模式打开一个文件,并写入current_ver文本内容。我们可以根据服务提供商、页面名称和当前日期构建文件名。这些捕获的数据将作为网站监控项目中未来比较的基线。

比较和变更检测

在后续执行中,我们检索更新的网页内容,并将其与存储的基线数据进行对比,以识别任何偏差或更改。以下是前面脚本的续写:

change_logs = pd.DataFrame()

for provider, page, link in zip(df['服务提供商'].
to_list(), df['页面名称'].to_list(), df['网页链接'].to_list()):
files = glob.glob(r"路径{}{}*.txt".format(provider, page))
files_sorted = sorted(files, key=os.path.getctime, reverse=True)
current_content = open(files_sorted[0], 'r', encoding="utf-8").readlines()
prior_content = open(files_sorted[1], 'r', encoding="utf-8").readlines()

comparison = difflib.context_diff(current_content, 
prior_content, n=3, lineterm='\n')

compared_text = "\n".join([line.rstrip() for line 
in'\n'.join(comparison).splitlines() if line.strip()])
if compared_text == '':
    change_description = '在' 
    + date.today().strftime('%Y-%m-%d') + '与' 
    + files_sorted[1].split('_')[2].split('.')[0] + '相比,未检测到任何更改'
else:
    if "找不到您要查找的页面" 
    in compared_text:
        change_description = '在' + 
        date.today().strftime('%Y-%m-%d') + '与' + 
        files_sorted[1].split('_')[2].split('.')[0] + '相比,URL已修改'
    else:
        change_description = '在' +
         date.today().strftime('%Y-%m-%d') + '与' + 
         files_sorted[1].split('_')[2].split('.')[0] + '相比,检测到变更'

temp_log = pd.DataFrame({'服务提供商': pd.Series(provider),
  '部分': pd.Series(page), '变更': pd.Series
  (change_description), '链接': pd.Series(link)})
change_logs = change_logs.append(temp_log)

comparison = difflib.context_diff(current_content, 
prior_content, n=3, lineterm='\n')

compared_text = "\n".join([line.rstrip() for line 
in'\n'.join(comparison).splitlines() if line.strip()])
if compared_text == '':
    change_description = '在' + date.today().strftime('%Y-%m-%d') + 
    '与' + files_sorted[1].split('_')[2].split('.')[0] + 
    '相比,未检测到任何更改'
else:
    if "找不到您要查找的页面"
     in compared_text:
        change_description = '在' + 
        date.today().strftime('%Y-%m-%d') + '与' +
         files_sorted[1].split('_')[2].split('.')[0] + '相比,URL已修改'
    else:
        change_description = '在' +
         date.today().strftime('%Y-%m-%d') + '与' +
          files_sorted[1].split('_')[2].split('.')[0] + '相比,检测到变更'

temp_log = pd.DataFrame({'服务提供商': 
pd.Series(provider), '部分': pd.Series(page),
'变更': pd.Series(change_description), '链接': pd.Series(link)})
change_logs = change_logs.append(temp_log)

我们创建一个名为change_logs的空DataFrame来存储任何已识别的变化的详细信息。使用pandas DataFrame,我们迭代遍历行以获取服务提供商、页面名称和网页链接。将它们分别记为provider、page和link。

在循环内部,我们收集与先前保存的文件模式匹配的文件集合。这个集合按文件创建时间排序,最新的文件排在前面。

然后,我们读取当前文件和先前文件的内容进行比较。difflib.context_diff()函数执行比较,并将结果存储在comparison变量中。

根据比较的文本内容,我们可以确定是否有任何变化,或者特定的消息是否指示页面丢失或URL已更改。

随后,我们构建change_description变量,记录日期和用于比较的先前文件的参考日期。使用获取的数据,我们生成一个临时DataFrame temp_log,其中包括服务提供商、页面名称、变更描述和网页链接。

最后,我们将temp_log添加到change_logs DataFrame中,收集所有检测到的变化的详细信息。

通知机制

在检测到变化时,使用通知机制来提醒用户。您可以使用Python库或外部API来进行通知传递。首先,导入发送通知所需的库,根据您选择的方法,您可能需要安装其他库或API。

对于电子邮件通知,我们将利用smtplib库通过SMTP服务器发送电子邮件。确保提供您的电子邮件凭据和SMTP服务器详细信息。

以下是一个展示电子邮件通知的代码片段:

import smtplib

def send_email_notification(subject, message, recipient):
    sender = '[email protected]'
    password = 'your-email-password'
    smtp_server = 'smtp.example.com'
    smtp_port = 587

    email_body = f'Subject: {subject}\n\n{message}'
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(sender, password)
        server.sendmail(sender, recipient, email_body)

# 使用方法:
subject = '网站变更通知'
message = '在网站上检测到变更。请审核。'
recipient = '[email protected]'
send_email_notification(subject, message, recipient)

对于短信通知,您可以集成像Twilio或Nexmo这样的外部API。这些API支持以编程方式发送短信。注册一个帐户,获取必要的API凭证,并安装相应的Python库。

以下是一个使用Twilio API演示短信通知的示例代码片段:

from twilio.rest import Client

def send_sms_notification(message, recipient):
    account_sid = 'your-account-sid'
    auth_token = 'your-auth-token'
    twilio_number = 'your-twilio-phone-number'

    client = Client(account_sid, auth_token)
    message = client.messages.create(
        body=message,
        from_=twilio_number,
        to=recipient
    )

# 使用方法:
message = '在网站上检测到变更。请审核。'
recipient = '+1234567890'
send_sms_notification(message, recipient)

日志记录和报告

由于组织将经常运行此脚本来跟踪变化,因此保持每次运行的输出记录非常重要。记录每个执行的信息,包括时间、持续时间和检测到的变化,可以促进此过程。我们可以使用这些数据生成摘要报告,显示随时间的趋势,并帮助了解网站更新的频率和性质。

我们通过导入适当的库来启动此过程,其中包括Python中的logging库。同时,我们必须设置日志级别和日志文件格式。

import logging

# 配置日志设置
logging.basicConfig(filename='website_monitoring.log', 
level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 记录信息消息
logging.info('网站监控已启动。')

# 记录检测到的变化
logging.info('在{date}检测到变化:{details}'
.format(date='2023-06-15', details='更新了主页内容。'))

# 记录错误消息
logging.error('检索网站内容时发生错误。')

为了从日志数据生成报告,我们可以使用matplotlib或seaborn等库创建可视化图表,总结随时间的变化。报告和可视化图表的选择将取决于跟踪的变化。

下面是一个生成简单线图以说明随时间变化频率的示例代码片段:

import matplotlib.pyplot as plt
import pandas as pd

# 将日志文件读入 pandas DataFrame
log_data = pd.read_csv('website_monitoring.log', 
delimiter=' - ', header=None, names=['Timestamp', 'Level', 'Message'])

# 将 Timestamp 列转换为 datetime 格式
log_data['Timestamp'] = pd.to_datetime(log_data
['Timestamp'], format='%Y-%m-%d %H:%M:%S')

# 按日期对数据进行分组并计算每天的更改次数
changes_per_day = log_data[log_data['Level'] == 'INFO']
.groupby(log_data['Timestamp'].dt.date).size()

# 绘制时间上的更改情况
plt.plot(changes_per_day.index, changes_per_day.values)
plt.xlabel('日期')
plt.ylabel('更改次数')
plt.title('网站内容变化趋势')
plt.xticks(rotation=45)
plt.show()

限制

在项目实施过程中可能会出现一些挑战,需要仔细考虑。这些限制包括网站结构变化、法律或道德约束以及网络爬虫或数据比较过程中的错误。

网站结构变化:动态网站经常进行修改,影响网络爬虫过程。需要调整爬虫代码以适应这些变化。定期监测和更新爬虫代码可以确保与不断变化的网站结构兼容。

法律和道德约束:遵循法律和道德准则对于网络爬虫至关重要。网站可能有禁止爬取或对数据收集施加限制的服务条款。尊重这些条款并负责地使用爬取的数据是确保合规性的关键。

网络爬虫和数据比较中的错误:网络爬虫涉及与外部网站的交互,可能会出现错误的可能性。在爬取过程中可能出现连接失败、超时或服务器问题。使用健壮的错误处理机制优雅地处理这些情况非常重要。此外,确保数据比较过程的准确性并考虑到可能的错误(如误报或漏报)对于可靠的结果至关重要。

权限和网站政策:在启动网络爬虫之前,验证目标网站是否允许爬取或获得网站所有者的必要许可是必要的。遵守网站的 robots.txt 文件、尊重其服务条款并注意请求频率是避免违规的重要考虑因素。

结论

总之,本项目成功创建了一个强大的 Python 工具,通过网络爬虫来跟踪网站更新。我们成功开发了一个具备网络爬虫、数据比较、通知、日志和报告等基本功能的工具。

在整个项目过程中,我们加深了对 HTML 的理解,磨练了文本处理技巧,并掌握了数据处理的艺术。借助 BeautifulSoup 和 requests 的能力,我们熟练掌握了使用 Python 进行网络爬虫和自动化任务的技能。此外,我们还开发了健壮的错误处理机制,获得了数据分析和报告的专业知识。

我们的工具是跟踪新闻文章、产品列表和其他网络内容变化的可靠解决方案。自动化的过程消除了手动更新的需求,确保信息保持最新和准确。

在这个过程中,我们获得了宝贵的知识和技能,包括:

  1. 使用 BeautifulSoup 和 requests 进行网络爬虫技术。
  2. 有效地从 HTML 结构中提取有价值的信息。
  3. 自动化任务以优化流程。
  4. 在网络爬虫过程中具备健壮的错误处理能力。
  5. 高级数据分析和比较,以识别变化。
  6. 创建全面的通知、日志和报告,以实现高效的跟踪和深入分析。

常见问题

本文中显示的媒体不归 Analytics Vidhya 所有,仅根据作者的自由裁量使用。