Python爬取RSS时如何提取带CDATA的pubDate并存储到数据库?
解决RSS中带CDATA的pubDate字段存储MySQL问题
问题根源
原代码存在以下核心问题导致报错:
- XML标签大小写不匹配:RSS中的标签是
<pubDate>,但代码里用a.find('pubdate')(小写)无法正确匹配,导致提取不到日期内容 - CDATA内容提取未处理:带CDATA的
<pubDate>内容在BeautifulSoup中需正确提取文本,原代码直接取.text可能出现空值或格式问题 - 日期格式不兼容:RSS的日期格式(如
Wed, 17 Aug 2022 14:32:47 +0530)无法直接存入MySQL的datetime字段,需转换格式 - 代码语法错误:导入模块语句格式错误,存在无效代码行,且
insertData方法未使用传入的date参数
修复步骤
1. 修正模块导入与无效代码
将导入语句拆分为独立行,删除无效代码:
from bs4 import BeautifulSoup import requests import pymysql from datetime import datetime
2. 正确提取pubDate内容
使用正确的标签名pubDate提取内容,并用strip()去除首尾空格:
pub_date_raw = a.find('pubDate').string.strip()
3. 转换日期格式为MySQL兼容格式
利用datetime模块解析RSS日期,转换为MySQL支持的格式:
# 解析RSS日期格式 parsed_date = datetime.strptime(pub_date_raw, '%a, %d %b %Y %H:%M:%S %z') # 转换为MySQL兼容的datetime对象 mysql_date = parsed_date.astimezone().replace(tzinfo=None)
4. 修正insertData方法
将date参数加入SQL插入语句和参数列表,确保数据库表的date字段类型为datetime或timestamp:
def insertData(self, title, date, url, description, source): myCursor = self.conn.cursor() query = "INSERT INTO `delhi`(`title`, `date`, `url`, `description`, `source`) VALUES(%s,%s,%s,%s,%s)" args = (title, date, url, description, source) myCursor.execute(query, args) self.conn.commit()
完整修正代码
from bs4 import BeautifulSoup import requests import pymysql from datetime import datetime headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } class ReadRss: def __init__(self, rss_url, headers): self.url = rss_url self.headers = headers self.conn = None self.soup = None self.articles = [] try: # 初始化数据库连接 self.conn = pymysql.connect( host="localhost", user="root", passwd="", db="my_python" ) # 请求RSS内容并主动抛出HTTP错误 self.r = requests.get(rss_url, headers=self.headers) self.r.raise_for_status() except Exception as e: print(f'获取URL失败: {rss_url}') print(f'错误信息: {e}') return try: # 使用xml解析器处理RSS内容 self.soup = BeautifulSoup(self.r.text, 'xml') except Exception as e: print(f'解析XML失败: {self.url}') print(f'错误信息: {e}') return self.articles = self.soup.find_all('item') for a in self.articles: try: # 提取各字段内容 title = a.find('title').string.strip() pub_date_raw = a.find('pubDate').string.strip() url = a.find('link').string.strip() if a.find('link') else a.link.next_sibling.replace('\n','').replace('\t','').strip() description = a.find('description').string.strip() if a.find('description') else '' # 转换日期格式 parsed_date = datetime.strptime(pub_date_raw, '%a, %d %b %Y %H:%M:%S %z') mysql_date = parsed_date.astimezone().replace(tzinfo=None) # 插入数据库 self.insertData(title, mysql_date, url, description, 'thehindu') except Exception as e: print(f'处理文章失败: {title if "title" in locals() else "未知标题"}') print(f'错误信息: {e}') continue # 关闭数据库连接 if self.conn: self.conn.close() def insertData(self, title, date, url, description, source): try: myCursor = self.conn.cursor() query = "INSERT INTO `delhi`(`title`, `date`, `url`, `description`, `source`) VALUES(%s,%s,%s,%s,%s)" args = (title, date, url, description, source) myCursor.execute(query, args) self.conn.commit() except Exception as e: print(f'插入数据库失败') print(f'错误信息: {e}') self.conn.rollback() if __name__ == '__main__': feed = ReadRss('https://www.thehindu.com/news/cities/Delhi/feeder/default.rss', headers)
关键注意事项
- 数据库表结构:确保
delhi表存在date字段,类型设置为datetime或timestamp - 解析器选择:使用
xml解析器比lxml更适合处理RSS这类XML内容 - 异常处理:新增单篇文章处理的异常捕获,避免一篇文章出错导致整个爬取中断
- 时区处理:通过
astimezone().replace(tzinfo=None)将带时区的日期转换为本地时间,适配MySQL的datetime类型
内容的提问来源于stack exchange,提问作者ASTHA JAIN
相关产品推荐
相关产品推荐

