详解python定时简单爬取网页新闻存入数据库并发送邮件


Posted in Python onNovember 27, 2020

本人小白一枚,简单记录下学校作业项目,代码十分简单,主要是对各个库的理解,希望能给别的初学者一点启发。

一、项目要求

1、程序可以从北京工业大学首页上爬取新闻内容:http://www.bjut.edu.cn

详解python定时简单爬取网页新闻存入数据库并发送邮件

2、程序可以将爬取下来的数据写入本地MySQL数据库中。

3、程序可以将爬取下来的数据发送到邮箱。

4、程序可以定时执行。

二、项目分析

1、爬虫部分利用requests库爬取html文本,再利用bs4中的BeaultifulSoup库来解析html文本,提取需要的内容。

2、使用pymysql库连接MySQL数据库,实现建表和插入内容操作。

3、使用smtplib库建立邮箱连接,再使用email库将文本信息加工成邮件消息并发送。

4、使用schedule库实现定时执行该程序。

三、代码分析

1、导入需要的库:

# 爬虫相关模块
import requests
from bs4 import BeautifulSoup
import pymysql

# 发邮件相关模块
import smtplib
from email.mime.text import MIMEText   
from email.header import Header 
import time

# 定时模块
import schedule

2、获取html文件:

# 连接获取html文本
def getHTMLtext(url):
  try:
    headers={
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
      } # 浏览器请求头
    r = requests.get(url, headers = headers, timeout = 30) # 获取连接
    r.raise_for_status() # 测试连接是否成功,若失败则报异常
    r.encoding = r.apparent_encoding # 解析编码
    return r.text
  except:
    return ""

其中必须添加请求头headers否则get请求时会返回错误页面。
raise_for_status()可以根据状态码判断连接对象的状态,如果成功便继续执行,若连接失败则抛出异常,因此利用try-except捕获。
apparent_encoding()方法可以解析判断可能的编码方式。

3、解析html提取数据:

首先观察网页源码确定新闻标签位置:

详解python定时简单爬取网页新闻存入数据库并发送邮件

# 解析html提取数据
def parseHTML(news, html):
  soup = BeautifulSoup(html, "html.parser") # 获取soup
  for i in soup.find(attrs = {'class' : 'list'}).find_all('li'): # 存放新闻的li标签
    date = i.p.string + '-' + i.h2.string # 日期
    href = i.a['href'] # 链接
    title = i.find('h1').string # 标题
    content = i.find_all('p')[1].string # 梗概
    news.append([date, href, title, content]) # 添加到列表中

可见所有新闻内容全部存放在class为”list”的div标签中,而每条新闻又存放在li标签中,因此利用find和find_all方法遍历所有li标签。

每个li标签中a标签的href属性存放新闻链接,h1标签存放新闻标题,h2标签存放日期,第一个p标签存放年、月,第二个p标签存放新闻梗概。依次取出对应标签中的文本内容,并将年月日拼接后依次存入news列表中。

4、存入数据库

# 存入数据库
def toMysql(news):
  conn = pymysql.connect(host = 'localhost', port = 3306, user = 'root', passwd = '数据库密码', db = '数据库名称',charset = 'gbk', connect_timeout = 1000)
  cursor = conn.cursor()
  
  sql = '''
  create table if not exists tb_news(
    日期 date, 
    链接 varchar(400),
    标题 varchar(400),
    梗概 varchar(400))
  '''
  
  cursor.execute(sql) # 建表
  
  for new in news: # 循环存入数据
    sql = 'insert into tb_news(日期, 链接, 标题, 梗概) values(%s, %s, %s, %s)'
    date = new[0]
    href = new[1]
    title = new[2]
    content = new[3]
    cursor.execute(sql, (date, href, title, content))
    
  conn.commit()
  conn.close()

由于新闻字数较多,存取时可能会有乱码以及数据过长存储失败的问题,与数据库编码有关,可以在MySQL的my.ini配置文件中修改默认编码为gbk。

5、发送邮件

# 发送邮件
def sendMail(news):
  from_addr = '发送邮箱' # 发送邮箱
  password = '16位授权码' # 邮箱授权码
  
  to_addr = '接收邮箱' # 接收邮箱
  
  mailhost = 'smtp.qq.com' # qq邮箱的smtp地址
  qqmail = smtplib.SMTP() # 建立SMTP对象
  qqmail.connect(mailhost, 25) # 25为SMTP常用端口
  qqmail.login(from_addr, password) # 登录邮箱
  
  content = ''
  for new in news: # 拼接邮件内容字符串
    content += '新闻时间:' + new[0] + '\n' + '新闻链接:' + new[1] + '\n' + '新闻标题:' + new[2] + '\n' + '新闻梗概:' + new[3] + '\n'
    content += '======================================================================\n'
    
  # 拼接题目字符串
  subject = time.strftime('%Y-%m-%d %X', time.localtime(time.time())) + '时爬取的北工大首页主要新闻\n'
  
  # 加工邮件message格式
  msg = MIMEText(content, 'plain', 'utf-8')
  msg['subject'] = Header(subject, 'utf-8')
  
  try:
    qqmail.sendmail(from_addr, to_addr, msg.as_string())
    print('发送成功')
  except:
    print('发送失败')
  qqmail.quit()

注意其中的密码不是指邮箱的登录密码,而是指邮箱的smtp授权码,qq邮箱可以再设置中开启smtp服务,并获取授权码。

详解python定时简单爬取网页新闻存入数据库并发送邮件

6、主函数

# 主函数
def main():
  news = []
  url = "http://www.bjut.edu.cn/"
  html = getHTMLtext(url)
	parseHTML(news, html)
	toMysql(news)
  print(news)
	sendMail(news)

输入北京工业大学官网的url并新建一个列表news用来存放消息,然后依次调用函数爬取新闻存入数据库并发到邮箱。为了检验上述程序是否可以完成任务,先调用依次main()函数并print(news)看看结果:

main() #测试需要,之后会删除

结果如下:

详解python定时简单爬取网页新闻存入数据库并发送邮件

详解python定时简单爬取网页新闻存入数据库并发送邮件

详解python定时简单爬取网页新闻存入数据库并发送邮件

由此可见程序执行正常。

7、定时执行

# 定时执行整个任务
schedule.every().monday.at("08:00").do(main) # 每周一早上八点执行main函数
while True:
  schedule.run_pending()
  time.sleep(1)

用死循环保证schedule一直运行。设定的是每周一早上8:00执行程序。

为了方便检查效果,先将运行时间改为每5s运行一次:

schedule.every(5).seconds.do(main)

详解python定时简单爬取网页新闻存入数据库并发送邮件

每5s便可以收到一封邮件,由此可见满足定时需求。至此程序结束。

四、完整代码

# 爬虫相关模块
import requests
from bs4 import BeautifulSoup
import pymysql

# 发邮件相关模块
import smtplib
from email.mime.text import MIMEText   
from email.header import Header 
import time

# 定时模块
import schedule

# 连接获取html文本
def getHTMLtext(url):
  try:
    headers={
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36",
    } # 浏览器请求头
    r = requests.get(url, headers = headers, timeout = 30) # 获取连接
    r.raise_for_status() # 测试连接是否成功,若失败则报异常
    r.encoding = r.apparent_encoding # 解析编码
    return r.text
  except:
    return ""


# 解析html提取数据
def parseHTML(news, html):
  soup = BeautifulSoup(html, "html.parser") # 获取soup
  for i in soup.find(attrs = {'class' : 'list'}).find_all('li'): # 存放新闻的li标签
    date = i.p.string + '-' + i.h2.string # 日期
    href = i.a['href'] # 链接
    title = i.find('h1').string # 标题
    content = i.find_all('p')[1].string # 梗概
    news.append([date, href, title, content]) # 添加到列表中

# 存入数据库
def toMysql(news):
  conn = pymysql.connect(host = 'localhost', port = 3306, user = 'root', passwd = '数据库密码', db = '数据库名称',charset = 'gbk', connect_timeout = 1000)
  cursor = conn.cursor()
  
  sql = '''
  create table if not exists tb_news(
    日期 date, 
    链接 varchar(400),
    标题 varchar(400),
    梗概 varchar(400))
  '''
  
  cursor.execute(sql) # 建表
  
  for new in news: # 循环存入数据
    sql = 'insert into tb_news(日期, 链接, 标题, 梗概) values(%s, %s, %s, %s)'
    date = new[0]
    href = new[1]
    title = new[2]
    content = new[3]
    cursor.execute(sql, (date, href, title, content))
    
  conn.commit()
  conn.close()

# 发送邮件
def sendMail(news):
  from_addr = '发送邮箱' # 发送邮箱
  password = '16位授权码' # 邮箱授权码
  
  to_addr = '接收邮箱' # 接收邮箱
  
  mailhost = 'smtp.qq.com' # qq邮箱的smtp地址
  qqmail = smtplib.SMTP() # 建立SMTP对象
  qqmail.connect(mailhost, 25) # 25为SMTP常用端口
  qqmail.login(from_addr, password) # 登录邮箱
  
  content = ''
  for new in news: # 拼接邮件内容字符串
    content += '新闻时间:' + new[0] + '\n' + '新闻链接:' + new[1] + '\n' + '新闻标题:' + new[2] + '\n' + '新闻梗概:' + new[3] + '\n'
    content += '======================================================================\n'
    
  # 拼接题目字符串
  subject = time.strftime('%Y-%m-%d %X', time.localtime(time.time())) + '时爬取的北工大首页主要新闻\n'
  
  # 加工邮件message格式
  msg = MIMEText(content, 'plain', 'utf-8')
  msg['subject'] = Header(subject, 'utf-8')
  
  try:
    qqmail.sendmail(from_addr, to_addr, msg.as_string())
    print('发送成功')
  except:
    print('发送失败')
  qqmail.quit()



# 主函数
def main():
  news = []
  url = "http://www.bjut.edu.cn/"
  html = getHTMLtext(url)
  parseHTML(news, html)
  print(news)
  sendMail(news)
  
# 定时执行整个任务
schedule.every().monday.at("08:00").do(main) # 每周一早上八点执行main函数
while True:
  schedule.run_pending()
  time.sleep(1)

到此这篇关于详解python定时简单爬取网页新闻存入数据库并发送邮件的文章就介绍到这了,更多相关python定时爬取网页内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现用户登陆邮件通知的方法
Jul 09 Python
python与C互相调用的方法详解
Jul 14 Python
基于Python和Scikit-Learn的机器学习探索
Oct 16 Python
Numpy数组的保存与读取方法
Apr 04 Python
Python for循环中的陷阱详解
Jul 13 Python
PyQt打开保存对话框的方法和使用详解
Feb 27 Python
Python实现的列表排序、反转操作示例
Mar 13 Python
对tensorflow 中tile函数的使用详解
Feb 07 Python
使用Python开发个京东上抢口罩的小实例(仅作技术研究学习使用)
Mar 10 Python
基于Keras 循环训练模型跑数据时内存泄漏的解决方式
Jun 11 Python
python zip()函数的使用示例
Sep 23 Python
python中pickle模块浅析
Dec 29 Python
五种Python转义表示法
Nov 27 #Python
Django如何继承AbstractUser扩展字段
Nov 27 #Python
如何使用 Flask 做一个评论系统
Nov 27 #Python
python+openCV对视频进行截取的实现
Nov 27 #Python
Python环境配置实现pip加速过程解析
Nov 27 #Python
python实现学生信息管理系统(精简版)
Nov 27 #Python
基于Python采集爬取微信公众号历史数据
Nov 27 #Python
You might like
PHP排序算法之快速排序(Quick Sort)及其优化算法详解
2018/04/21 PHP
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
JavaScript类和继承 constructor属性
2010/03/04 Javascript
setTimeout和setInterval的区别你真的了解吗?
2011/03/31 Javascript
关于JS中的闭包浅谈
2013/08/23 Javascript
jQuery队列操作方法实例
2014/06/11 Javascript
jQuery绑定事件的四种方式介绍
2016/10/31 Javascript
js实现九宫格拼图小游戏
2017/02/13 Javascript
js实现返回顶部效果
2017/03/10 Javascript
微信小程序实现的五星评价功能示例
2019/04/25 Javascript
layui 选择列表,打勾,点击确定返回数据的例子
2019/09/02 Javascript
JQuery使用属性addClass、removeClass和toggleClass实现增加和删除类操作示例
2019/11/18 jQuery
微信小程序如何加载数据库真实数据的实现
2020/03/04 Javascript
深入理解Python中命名空间的查找规则LEGB
2015/08/06 Python
Python操作RabbitMQ服务器实现消息队列的路由功能
2016/06/29 Python
深入理解python中的atexit模块
2017/03/07 Python
python中返回矩阵的行列方法
2018/04/04 Python
python实现linux下抓包并存库功能
2018/07/18 Python
python语音识别实践之百度语音API
2018/08/30 Python
python 检查文件mime类型的方法
2018/12/08 Python
python使用xlsxwriter实现有向无环图到Excel的转换
2018/12/12 Python
python爬虫 正则表达式解析
2019/09/28 Python
PyCharm中配置PySide2的图文教程
2020/06/18 Python
如何用 Python 处理不平衡数据集
2021/01/04 Python
德国大型的家具商店:Pharao24.de
2016/10/02 全球购物
写一个用矩形法求定积分的通用函数
2012/11/08 面试题
简述安装Slackware Linux系统的过程
2012/05/08 面试题
实习生自我鉴定
2013/12/12 职场文书
学校组织向国旗敬礼活动方案(中小学适用)
2014/09/27 职场文书
好好学习保证书
2015/02/26 职场文书
出纳试用期自我评价
2015/03/10 职场文书
销售开票员岗位职责
2015/04/15 职场文书
开业庆典嘉宾致辞
2015/08/01 职场文书
《平行四边形的面积》教学反思
2016/02/16 职场文书
MySQL数据库超时设置配置的方法实例
2021/10/15 MySQL
Python Pygame实战之塔防游戏的实现
2022/03/17 Python