背景
有时候需要关注一些网站的消息通知,时刻查询又比较耗费时间精力,所以想到用Python脚本定时访问,检索到新通知时发送微信提醒
流程
整体流程包含以下步骤:
- 请求获取页面信息
- 解析页面信息,获取一段时间内的通知列表
- 发送微信提醒
实现
以CSDN “问答”模块为例说明代码实现
获取页面信息
发送http请求获取
import requests
def getHtml(url):
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'}
resp=requests.get(url, headers = headers, verify = False)
now = datetime.now()
now_str = now.strftime("%Y-%m-%d %H:%M:%S")
if resp.status_code == requests.codes.ok:
print("{0} request code: {1}, url: {2}".format(now_str, resp.status_code, url))
content = resp.text.encode(resp.encoding).decode(resp.apparent_encoding)
return content
print("{0} request code: {1}, url: {2}".format(now_str, resp.status_code, url))
return ""
页面解析
利用浏览器中的“开发者工具”可以找到模块对应的代码。鼠标放到代码处,对应模块会高亮。
我们可以看到,我们希望解析的数据在class="content-left-index'模块内。这个模块内部有很多的列表,每个列表中我们需要关注“标题”栏(class="title-box")和“日期”栏(class=“date”)
然后我们就可以利用Python内部的工具库将这些参数解析出来了。我这里用的是BeautifulSoup,它可以做节点遍历之类的操作,比较方便。文档:Beautiful Soup 4.4.0 文档 — Beautiful Soup 4.2.0 中文 文档
from bs4 import BeautifulSoup
from datetime import datetime
def getRowId(self, link):
tmp_list = link.split('/')
last_idx = len(tmp_list) - 1
row_id = '{0}_{1}'.format(self.id_prefix, tmp_list[last_idx])
return row_id
def parseHtml(self, row_list):
today = datetime.today()
html_doc = getHtml(self.url)
soup = BeautifulSoup(html_doc, 'lxml')
tbody = soup.find_all('div', 'question_right')
for node in tbody:
title_box = node.find(attrs={'class':'title-box'})
date_div = node.find(attrs={"class":"date"})
if title_box == None or title_box.a == None or date_div == None:
print("find title-box or title_box.a or date failed, skip node!")
continue
while len(date_div['class']) > 1:
date_div = date_div.find_next(attrs={"class":"date"})
date_str = date_div.string
date = datetime.strptime(date_str, '%Y-%m-%d %H:%M')
if date.timestamp() > today.timestamp() - self.update_gap_ts:
link = title_box.a['href']
row_id = self.getRowId(link)
row_dict = {"id": row_id,
"title": title_box.a.h2.string,
"link": self.link_prefix + link,
"date": date}
row_list.append(row_dict)
return
self中参数值设置
self.id_prefix = "csdn" // 各个网站的标识
self.url='https://ask.csdn.net/?spm=1001.2100.3001.4492'
self.link_prefix = "" // 部分页面中link为相对路径,所以需要拼上prefix
self.update_gap_ts = 5 * MINUTE_TS // 关注5分钟内发布的消息
消息通知
发现新消息时发送微信通知。这里我用的是pushplus,关注公众号之后,可以通过公众号发送通知不需要额外登录微信,没有封号的风险。内容用html展示,消息中会自动解析。
官方文档:介绍 | pushplus 文档中心
import requests
def push(self, title, row_list):
row_len = str(len(row_list))
content = '''
<html lang="en">
<body>
<p>共收到''' + row_len + '''条新通知</p>
<ul>
'''
for row in row_list:
content += '<li><a href="'
content += row['link']
content += '">'
content += row['title']
content += '</a></li>'
content += '''
</ul>
</body>
</html>
'''
data = {"token":self.token, "title":title, "content":content}
body = json.dumps(data).encode(encoding='utf-8')
requests.post(self.url, data=body, headers=self.headers)
定期访问
脚本写完了,需要定期发起页面访问。这里用的crontab,具体配置可以参考:Linux crontab 命令 | 菜鸟教程
遇到的问题:
遇到的问题基本都有很多人给出了解决方案,这里就只贴链接了
- 访问页面失败,增加‘User-Agent’请求头解决:python Python爬虫防封杀方法集合 - 御虫师 - 博客园
- 请求报错,requests.exceptions.SSLError:requests.exceptions.SSLError 请求异常,SSL错误,证书认证失败问题解决_明而决之的博客-CSDN博客_requests.exceptions.sslerror
- 返回的页面中的中文为乱码的问题:Python使用request包请求网页乱码解决方法_Python之眼的博客-CSDN博客