详解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 相关文章推荐
pyqt4教程之实现半透明的天气预报界面示例
Mar 02 Python
python读取浮点数和读取文本文件示例
May 06 Python
Python编程之字符串模板(Template)用法实例分析
Jul 22 Python
python使用插值法画出平滑曲线
Dec 15 Python
pyqt5让图片自适应QLabel大小上以及移除已显示的图片方法
Jun 21 Python
python和c语言的主要区别总结
Jul 07 Python
Python之数据序列化(json、pickle、shelve)详解
Aug 30 Python
Django中间件拦截未登录url实例详解
Sep 03 Python
python实现宿舍管理系统
Nov 22 Python
Django中modelform组件实例用法总结
Feb 10 Python
Python日志打印里logging.getLogger源码分析详解
Jan 17 Python
Python实现机器学习算法的分类
Jun 03 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之curl设置超时实例
2014/11/03 PHP
Mac系统下使用brew搭建PHP(LNMP/LAMP)开发环境
2015/03/03 PHP
php递归调用删除数组空值元素的方法
2015/04/28 PHP
Yii2隐藏frontend/web和backend/web的方法
2015/12/12 PHP
PHP实现的oracle分页函数实例
2016/01/25 PHP
php实现与python进行socket通信的方法示例
2017/08/30 PHP
HTML-CSS群中单选引发的“事件”
2007/03/05 Javascript
用js做一个小游戏平台 (一)
2009/12/29 Javascript
用jquery的方法制作一个简单的导航栏
2014/06/23 Javascript
使用CDN和AJAX加速WordPress中jQuery的加载
2015/12/05 Javascript
AngularJS基础 ng-mouseleave 指令详解
2016/08/02 Javascript
jQuery 的 ready()的纯js替代方法
2016/11/20 Javascript
懒加载实现的分页&&网站footer自适应
2016/12/21 Javascript
使用vue制作FullPage页面滚动效果
2017/08/21 Javascript
详解10分钟学会vue滚动行为
2017/09/21 Javascript
使用JS获取SessionStorage的值
2018/01/12 Javascript
JavaScript 对引擎、运行时、调用堆栈的概述理解
2018/10/22 Javascript
微信小程序身份证验证方法实现详解
2019/06/28 Javascript
详解vue-cli项目开发/生产环境代理实现跨域请求
2019/07/23 Javascript
微信小程序向Java后台传输参数的方法实现
2020/12/10 Javascript
Python切片索引用法示例
2018/05/15 Python
Django中ORM外键和表的关系详解
2019/05/20 Python
tensorflow指定CPU与GPU运算的方法实现
2020/04/21 Python
Python基于numpy模块实现回归预测
2020/05/14 Python
keras 读取多标签图像数据方式
2020/06/12 Python
Python基于Serializer实现字段验证及序列化
2020/11/04 Python
Lungolivigno Fashion官网:高级时装在线购物
2020/10/17 全球购物
js正则匹配markdown里的图片标签的实现
2021/03/24 Javascript
新教师工作感言
2014/02/16 职场文书
《奇妙的国际互联网》 教学反思
2014/02/25 职场文书
二人合伙经营协议书
2014/09/13 职场文书
2014年残疾人工作总结
2014/12/06 职场文书
西湖英语导游词
2015/02/06 职场文书
农村环境卫生倡议书
2015/04/29 职场文书
致创业的您:这类人不适合餐饮创业
2019/08/19 职场文书
Python数据可视化之用Matplotlib绘制常用图形
2021/06/03 Python