详解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自动连接ssh的方法
Mar 07 Python
Python使用wxPython实现计算器
Jan 30 Python
Django 实现购物车功能的示例代码
Oct 08 Python
python write无法写入文件的解决方法
Jan 23 Python
pandas 中对特征进行硬编码和onehot编码的实现
Dec 20 Python
jupyter lab的目录调整及设置默认浏览器为chrome的方法
Apr 10 Python
在jupyter notebook中调用.ipynb文件方式
Apr 14 Python
Python自动发送和收取邮件的方法
Aug 12 Python
Python自动创建Excel并获取内容
Sep 16 Python
python regex库实例用法总结
Jan 03 Python
python+selenium实现12306模拟登录的步骤
Jan 21 Python
变长双向rnn的正确使用姿势教学
May 31 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中冒号、endif、endwhile、endfor使用介绍
2010/04/28 PHP
解析Win7 XAMPP apache无法启动的问题
2013/06/26 PHP
php异步多线程swoole用法实例
2014/11/14 PHP
PHP获取用户访问IP地址的5种方法
2016/05/16 PHP
PHP与服务器文件系统的简单交互
2016/10/21 PHP
PHP基于新浪IP库获取IP详细地址的方法
2017/05/04 PHP
wordpress自定义标签云与随机获取标签的方法详解
2019/03/22 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
2019/12/30 PHP
Nigma vs Alliance BO5 第四场2.14
2021/03/10 DOTA
用js实现控制内容的向上向下滚动效果
2007/06/26 Javascript
让网页根据不同IE版本显示不同的内容
2009/02/08 Javascript
Extjs中的GridPanel隐藏列会显示在menuDisabled中解决方法
2013/01/27 Javascript
两个数组去重的JS代码
2013/12/04 Javascript
js substring从右边获取指定长度字符串(示例代码)
2013/12/23 Javascript
JS实现简单的二维矩阵乘积运算
2016/01/26 Javascript
详解React-Todos入门例子
2016/11/08 Javascript
JS动态遍历json中所有键值对的方法(不知道属性名的情况)
2016/12/28 Javascript
javascript ES6 新增了let命令使用介绍
2017/07/07 Javascript
改变vue请求过来的数据中的某一项值的方法(详解)
2018/03/08 Javascript
Vue实现移动端拖拽交换位置
2020/07/29 Javascript
vue render函数动态加载img的src路径操作
2020/10/26 Javascript
Tensorflow卷积神经网络实例进阶
2018/05/24 Python
python爬取cnvd漏洞库信息的实例
2019/02/14 Python
python 字典的打印实现
2019/09/26 Python
python base64库给用户名或密码加密的流程
2020/01/02 Python
python如何查看网页代码
2020/06/07 Python
解决redis与Python交互取出来的是bytes类型的问题
2020/07/16 Python
python 基于selenium实现鼠标拖拽功能
2020/12/24 Python
selenium+python实现基本自动化测试的示例代码
2021/01/27 Python
pycharm进入时每次都是insert模式的解决方式
2021/02/05 Python
css3一款3D字体带阴影效果的实现步骤
2013/03/20 HTML / CSS
Ryderwear美国官网:澳大利亚高端健身训练装备品牌
2018/04/24 全球购物
员工安全承诺书
2014/05/22 职场文书
销售目标责任书
2014/07/23 职场文书
银行党员批评与自我批评
2014/10/15 职场文书
欠款起诉书范文
2015/05/19 职场文书