Python实现定时爬取新闻、存入MySQL并发送邮件的完整教程

Evan
Evan
发布时间:2026-10-14 | 4人浏览过
原创

本文详细介绍如何使用Python编写一个自动化脚本,定时从北京工业大学官网抓取新闻数据。通过requests和BS4解析HTML,利用pymysql将数据存入MySQL数据库,并结合smtplib实现邮件自动发送。文章涵盖环境配置、代码逻辑分析及schedule定时器的使用方法,适合初学者参考。

本文档记录了一个简单的学校作业项目,旨在帮助初学者理解相关库的使用。代码逻辑较为基础,希望能为其他入门者提供一定的启发和参考。

项目需求概述

一、项目需求概述

1. 程序需能够从北京工业大学官方网站(http://www.bjut.edu.cn)抓取新闻内容。

2. 程序需具备将抓取到的数据写入本地MySQL数据库的功能。

3. 程序需支持将抓取到的数据通过电子邮件发送出去。

4. 程序需支持定时自动执行上述操作。

技术方案分析

二、技术方案分析

1. 爬虫部分:使用requests库获取HTML源码,利用bs4库中的BeautifulSoup解析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

获取HTML页面

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 ""

在发起GET请求时,必须设置请求头headers,否则可能返回错误页面。\n\n调用raise_for_status()方法可根据HTTP状态码判断连接状态,若成功则继续执行,若失败则抛出异常,因此建议使用try-except结构进行捕获处理。\n\n使用apparent_encoding()方法可以解析并判断网页可能的编码格式。

解析HTML与数据提取

3. 解析HTML并提取数据:

首先检查网页源码以确定新闻标签的具体位置:


# 解析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()

需要注意的是,代码中的password参数并非邮箱登录密码,而是邮箱的SMTP授权码。对于QQ邮箱,需在设置中开启SMTP服务并获取相应的授权码。

主函数逻辑

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()函数并打印news列表以检查结果:


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

运行结果如下:



从结果可以看出,程序执行正常。

定时任务配置

7. 实现定时执行:


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

使用死循环确保schedule模块持续运行。设定程序在每周一早上8:00执行。

为了便于观察运行效果,先将执行间隔修改为每5秒运行一次:


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

每5秒即可收到一封邮件,证明定时功能满足需求。至此,程序开发结束。

完整代码展示

四、完整代码展示


# 爬虫相关模块
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 相关产品和应用

全部下载

专题列表