详解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实现linux下使用xcopy的方法
Jun 28 Python
利用Python自动监控网站并发送邮件告警的方法
Aug 24 Python
Python实现屏幕截图的代码及函数详解
Oct 01 Python
Python读取sqlite数据库文件的方法分析
Aug 07 Python
Python实现动态图解析、合成与倒放
Jan 18 Python
使用python客户端访问impala的操作方式
Mar 28 Python
完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误
Apr 01 Python
parser.add_argument中的action使用
Apr 20 Python
基于python 取余问题(%)详解
Jun 03 Python
python接口自动化之ConfigParser配置文件的使用详解
Aug 03 Python
python画条形图的具体代码
Apr 20 Python
Python可视化神器pyecharts之绘制地理图表练习
Jul 07 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 array_flip() 删除数组重复元素
2009/01/14 PHP
jQuery下扩展插件和拓展函数的写法(匿名函数使用的典型例子)
2010/10/20 Javascript
jquery formValidator插件ajax验证 内容不做任何修改再离开提示错误的bug解决方法
2013/01/04 Javascript
jQuery文本框(input textare)事件绑定方法教程
2013/04/24 Javascript
jquery 清空file域示例(兼容个浏览器)
2013/10/11 Javascript
JavaScript不使用prototype和new实现继承机制
2014/12/29 Javascript
原生Js实现简易烟花爆炸效果的方法
2015/03/20 Javascript
javascript实现仿IE顶部的可关闭警告条
2015/05/05 Javascript
jQuery实现提示密码强度的代码
2015/07/15 Javascript
jQuery on()绑定动态元素出现的问题小结
2016/02/19 Javascript
BootStrap中的表单大全
2016/09/07 Javascript
JS实现上传图片的三种方法并实现预览图片功能
2017/07/14 Javascript
Node接收电子邮件的实例代码
2017/07/21 Javascript
js 获取html5的data属性实现方法
2017/07/28 Javascript
JavaScript 数组的进化与性能分析
2017/09/18 Javascript
MUI顶部选项卡的用法(tab-top-webview-main)详解
2017/10/08 Javascript
Vue前端开发规范整理(推荐)
2018/04/23 Javascript
JS实现简单打字测试
2020/06/24 Javascript
[01:18:43]2014 DOTA2华西杯精英邀请赛5 24 iG VS DK
2014/05/25 DOTA
python ddt实现数据驱动
2018/03/14 Python
django中静态文件配置static的方法
2018/05/20 Python
Python生成短uuid的方法实例详解
2018/05/29 Python
Python实现快速傅里叶变换的方法(FFT)
2018/07/21 Python
python里 super类的工作原理详解
2019/06/19 Python
python openpyxl使用方法详解
2019/07/18 Python
英国游戏机和游戏购物网站:365games.co.uk
2018/06/18 全球购物
自我推荐书
2013/12/04 职场文书
爱心活动计划书
2014/04/26 职场文书
厂区绿化方案
2014/05/08 职场文书
工程造价专业求职信
2014/07/17 职场文书
农村优秀教师事迹材料
2014/08/27 职场文书
结婚老公保证书
2015/02/26 职场文书
2015年乡镇纪委工作总结
2015/05/26 职场文书
毕业欢送晚会主持词
2019/06/25 职场文书
详细聊聊MySQL中慢SQL优化的方向
2021/08/30 MySQL
python缺失值填充方法示例代码
2022/12/24 Python