指定时间间隔爬取一次的延时爬虫
因为最近有比赛快出入围决赛名单了,抑制不住内心的激动隔几分钟就刷新一下网页,干脆写了个爬虫每10秒访问一次,如果有更新直接发邮箱通知队友们
当然,在没告知队友的情况下这封邮件理所应当的被当成了钓鱼邮件,下面记录一下中间不太懂的过程
本文用了requests
HTTP库请求网站,beautifulsoup
解析网页,smtplib
提供SMTP邮件传输协议服务,email
库构造邮件,以及用了sched
时间调度器和time
库来控制一段延时执行函数
import requests
from bs4 import BeautifulSoup
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import sched, time
main()
对于爬虫,先弄清页面结构,因为页面有个很显眼的最新公告,有活动通知才更新一次,官网正在举办的只有这一个比赛,可以肯定会在这里出现,分析这个盒子模型
<ul class="list-unstyled list-unstyled1" style="margin-bottom:0;">
<a href="http://xxxxxxxxxx"></a>
<li><span>[作品赛通知]</span>
<a href="http://xxxxxxxxxxx/view/156" title="2020年第十三届全国大学生信息安全竞赛-作品赛决赛团队名单" target="_blank">2020年第十三届全国大学生信息安全竞赛-...</a>
</li>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
直接用获取页面用beautifulsoup
解析后使用find__all() 获取指定class的ul,就能取到最新通知里的所有东西,再用find_next()函数取匹配到的第一个a标签
url = "官网url"
r = requests.get(url)
soup = BeautifulSoup(r.text, "html.parser")
uls = soup.find_all("ul", "list-unstyled list-unstyled1")[0].find_next("a")
得到这个
<a href="http://xxxxxxxxxxx/view/156" title="2020年第十三届全国大学生信息安全竞赛-作品赛决赛团队名单" target="_blank">2020年第十三届全国大学生信息安全竞赛-...</a>
我取出了href的跳转链接和显示的内容作为对比参照,其实可以使用href和title更好一些
# title 为显示的内容,uls[]借用beautifulsoup的解析提取href, 用strip()去除首尾空格
title = uls.string.strip()
href = uls['href'].strip()
判断逻辑,如果 href 和 title 有一个不等于最新公告第一条就发邮件通知,否则延时10秒重新执行
if href != "http://xxxxxxxxx/view/156" or title != "2020年第十三届全国大学生信息安全竞赛-...":
# 已更新,发邮件通知
html = '<h3>别紧张,俺的爬虫发现官网更新了名单...快去看</h3><br><p>{}</p><a href="{}">就是这个地址</a>'.format(title, href)
mail(html)
else:
print("内容未更新")
# 延时10秒执行main函数
s.enter(10, 0, main)
mail()
这里借鉴了菜鸟教程的Python SMTP发送邮件
# 第三方 SMTP 服务
mail_host="smtp.qq.com" #设置服务器
mail_user="xxxxxxx@qq.com" #用户名
mail_pass="qpappeklyuhwjcgc" #口令
# 设置发送者和发送目标
sender = 'jerryxxxxxx@qq.com'
receivers = ['队友1邮箱', '队友2邮箱', '队友3邮箱', '队友4邮箱']
发送者甚至可以填虚假的,让人找不到到底是谁发的,不过可以利用qq邮箱的查看原文找到ip地址,当然一般人是不知道的
关于口令需要使用qq邮箱的SMTP服务,配置方法如下
邮件的内容我从main()传入的html
# 设置邮件内容
message = MIMEText(html, 'html', 'utf-8')
message['From'] = "帅气的xx"
message['To'] = "孩儿们"
如果按照菜鸟教程的方法在发送给其他人的时候会将邮件自动放入对方的垃圾箱里,设置邮件内容时不声明编码格式直接赋值成字符串就不会被丢进垃圾箱了
message['From'] = Header("菜鸟教程", 'utf-8')
# 不声明编码格式,改成下面的
message['From'] = "菜鸟教程"
sched控制定时延时执行
# 第一个参数确定任务的时间,返回从某个特定的时间到现在经历的秒数
# 第二个参数以某种人为的方式衡量时间
# 生成调度器
s = sched.scheduler(time.time, time.sleep)
scheduler.enter
(delay, priority, action, argument=(), kwargs={})
安排延后 delay 时间单位的事件。 除了相对时间,其他参数、效果和返回值
第一个参数是一个整数或浮点数,代表多少秒后执行这个action任务
第二个参数priority是优先级,0代表优先级最高,1次之,2次次之,当
两个任务是预定在同一个时刻执行时,根据优先级决定谁先执行。
第三个参数就是你要执行的任务,可以简单理解成你要执行任务的函数的函数名
第四个参数是你要传入这个定时执行函数名函数的参数,最好用括号包起来,如果只传入一个
import requests
from bs4 import BeautifulSoup
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import sched, time
def main():
url = "官网url"
r = requests.get(url)
soup = BeautifulSoup(r.text, "html.parser")
uls = soup.find_all("ul", "list-unstyled list-unstyled1")[0].find_next("a")
# title 为显示的内容,uls[]借用beautifulsoup的解析提取href, 用strip()去除首尾空格
title = uls.string.strip()
href = uls['href'].strip()
# print(href, title)
if href != "http://xxxxxxxxx/view/156" or title != "2020年第十三届全国大学生信息安全竞赛-...":
# 已更新,发邮件通知
html = '<h3>别紧张,俺的爬虫发现官网更新了名单...快去看</h3><br><p>{}</p><a href="{}">就是这个地址</a>'.format(title, href)
mail(html)
else:
print("内容未更新")
# 延时10秒执行main函数
s.enter(10, 0, main)
def mail(html):
# 第三方 SMTP 服务
mail_host="smtp.qq.com" #设置服务器
mail_user="xxxxxxx@qq.com" #用户名
mail_pass="qpappeklyuhwjcgc" #口令
# 设置发送者和发送目标
sender = 'jerryxxxxxx@qq.com'
receivers = ['队友1邮箱', '队友2邮箱', '队友3邮箱', '队友4邮箱']
# 设置邮件内容
message = MIMEText(html, 'html', 'utf-8')
message['From'] = "帅气的"
message['To'] = "孩儿们"
subject = '信息安全作品赛通知'
message['Subject'] = subject
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25) # 25 为 SMTP 端口号
smtpObj.login(mail_user,mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
print("邮件发送成功")
except smtplib.SMTPException:
print("Error: 无法发送邮件")
if __name__ == "__main__":
# 生成调度器
s = sched.scheduler(time.time, time.sleep)
s.enter(10, 0, main)
s.run()
本文地址:https://blog.csdn.net/qq_40654505/article/details/107569997