项目场景:
豆瓣的某小组,经常会有非常优惠的购物活动,但是僧多肉少,晚一些就没机会了。所以我需要时刻监控该界面,一旦出现关键词(开车),就自动向我邮箱发送信件。
前期准备:
我自认为,程序员做什么事情之前,都要进行一番百度,查阅前人是否有进行过这项工作,闭门造车是当不好程序员的。
更夫
- 在github上找到一款名为更夫的,使用go语言编写的前后端分离项目。
- 提供的在线demo网站能看得出思路如何:
- 设置网址
- 设置循环时间
- 设置抓取规则
- 同步数据库,若数据库没有,就发邮件通知用户
- 若数据库有,就更新数据库。
- 但是抓取规则是用正则编写,比较复杂。并且它发起的请求没有能携带cookie,浏览器头等,会被反爬处理。
- 并且go环境我不熟悉,于是pass。
page monitor
- 发现谷歌商店有很多监控网页的插件,不需要搭建环境,使用本地计算机发起请求,免除了一定反爬风险。
- 但是仔细查阅又发现,该类插件主要是完成类似抢票的任务:定时刷新网页,若网页有变化,浏览器弹窗通知用户。不符合我的需求,我要求是有关键字出现才提醒我,所以pass
自己的思路
- java, go语言等发起请求太复杂,用python最简便
- 正则表达式太负责,用xpath解析比较方便
- 需要有数据库,或一个txt文件,记录已经获取的信息,防止重复发送邮件。
- 程序需长期运行,所以需要云服务器
- 请求时间不能太短,防止被反爬。
- 所以流程如下所示(用markdow画图)
代码:
import requests
from lxml import etree
import smtplib
from email.mime.text import MIMEText
import time
def monitor():
headers = {"User-Agent":"XXX",
"Cookie":r'XXX',
"Host":"www.douban.com"}
data = requests.get(r"https://www.douban.com/group/656297/", headers=headers).content.decode("UTF-8")
dom_tree = etree.HTML(data)
result_titles = dom_tree.xpath(r'//td[@class="title"]/a/@title')
result_hrefs = dom_tree.xpath(r'//td[@class="title"]/a/@href')
result = zip(result_titles, result_hrefs)
old_data = read_csv()
new_data = []
mail_data = []
for i in result:
temp = []
if ("" in i[0]) and (i[1] not in old_data):
# print(i[0])
# print(i[1])
temp.append(i[0])
temp.append(i[1])
new_data.append(i[1])
mail_data.append(temp)
# print(mail_data)
for i in mail_data:
# print(i)
mail(i[0], i[1])
save_csv(new_data)
def read_csv():
result = []
with open(r"douban.txt", "r") as f:
for i in f.readlines():
result.append(i.replace("\n",""))
return result
def save_csv(data):
with open(r"douban.txt", "a") as f:
for i in data:
f.write(i)
f.write("\n")
def mail(title, href):
msg_from = '' # 发送方邮箱
passwd = '' # 填入发送方邮箱的授权码
msg_to = '' # 收件人邮箱
subject = "豆瓣有新提醒啦" # 主题
content = "豆瓣有更新啦,标题为: {}, 链接地址为: {}".format(title, href)
msg = MIMEText(content)
msg['Subject'] = subject
msg['From'] = msg_from
msg['To'] = msg_to
try:
s = smtplib.SMTP_SSL("smtp.qq.com", 465)
s.login(msg_from, passwd)
s.sendmail(msg_from, msg_to, msg.as_string())
print("发送成功")
except s.SMTPException as e:
with open(r"exception.txt", "a") as f:
f.write(e)
finally:
s.quit()
if __name__ == '__main__':
while True:
monitor()
time.sleep(600)
宝塔部署
我还是认为,有好用的工具为啥不用。
- 安装python项目管理器
- 设置项目
- 安装第三方库
- 启动就完事了