1 引言
在大数据与数字化信息快速迭代的行业背景下,新闻文本数据是舆情监测、行业研判、舆情风控、资讯聚合领域的核心数据源。传统人工采集方式存在采集效率低、数据维度单一、时效性差、人力成本高等痛点,无法满足规模化、精准化的数据采集需求。
Python 凭借轻量化的语法特性、成熟的爬虫生态库、丰富的数据处理工具,成为轻量化定向爬虫开发的首选编程语言。本文基于 Requests+BeautifulSoup 技术栈,搭建一款结构化关键词定向新闻爬虫,实现新闻资讯定向抓取、文本解析、关键词过滤、本地化持久化存储。文章从技术原理、环境部署、代码分层实现、逻辑解析、优化方案多角度展开,完整落地新闻爬虫开发流程,适用于技术开发者、数据分析从业者入门学习,所有代码可直接编译运行。
2 技术栈与开发环境搭建
2.1 核心技术栈选型
本次爬虫采用静态网页爬虫方案,适配主流新闻门户网站静态渲染页面,技术栈精简且稳定性高,各组件分工明确:
- 网络请求库 Requests:模拟HTTP/HTTPS协议发起网络请求,替代原生urllib库,支持自定义请求头、超时配置、编码自适应,适配绝大多数静态网页请求场景。
- 网页解析库 BeautifulSoup4:基于HTML/XML文档解析引擎,通过CSS选择器完成DOM节点定位,实现结构化数据提取,相较于正则表达式,容错率更高、代码可读性更强。
- 数据存储模块 CSV:轻量化文本存储格式,兼容Excel、数据库、数据分析工具,无需额外部署环境,适合中小型量级新闻数据持久化。
- 辅助工具库:time库实现请求休眠防封禁;re正则库完成文本清洗、冗余字符过滤。
2.2 爬虫合规与风控规范
爬虫开发必须遵循行业合规准则与网络安全法规,规避法律风险与服务器风控限制:
- 遵循网站 robots.txt 协议,仅爬取公开非授权加密的公共资讯数据;
- 设置请求休眠间隔,控制请求频率,规避高频访问造成的服务器负载压力;
- 禁止篡改请求参数、恶意高频爆破爬取,本文代码仅用于技术学习与科研分析。
3 新闻爬虫架构设计与核心原理
3.1 整体架构流程
本爬虫采用分层模块化设计,将请求、解析、筛选、存储逻辑解耦,降低代码耦合度,便于后期迭代优化。整体执行流程分为四大核心模块:
- 网络请求层:携带伪装请求头向目标域名发起GET请求,获取网页原始HTML源码;
- 数据解析层:通过DOM节点筛选,提取新闻标题、发布时间、源站链接、媒体来源等元数据;
- 关键词过滤层:基于字符串匹配规则,筛选含目标关键词的有效新闻数据,剔除冗余资讯;
- 持久化存储层:清洗正文文本,结构化录入CSV文件,完成数据落地存储。
3.2 反爬基础规避方案
多数新闻网站具备基础UA校验反爬机制,程序通过自定义请求头模拟真人浏览器访问,屏蔽服务器非法爬虫拦截判定,同时配置超时机制,规避网络卡顿导致的程序阻塞。
4 爬虫代码实现与分层解析
本文以百度新闻为爬取靶站,开发通用型关键词新闻爬虫,代码采用面向过程模块化编写,适配二次开发与网站迁移,完整代码及详细注解如下。
4.1 完整可运行代码
python
# 导入标准库与第三方依赖库
import requests
from bs4 import BeautifulSoup
import csv
import time
import re
# ==================== 全局配置参数(可自定义迭代)====================
BASE_URL = "https://news.baidu.com" # 靶站域名
# 浏览器伪装请求头,绕过基础UA反爬
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
}
KEYWORD = "人工智能" # 检索关键词
MAX_COUNT = 20 # 最大采集条数
SLEEP_TIME = 1 # 请求休眠间隔(秒)
SAVE_FILE = "news_keyword_data.csv" # 数据存储文件名
# ===================================================================
def get_html(target_url: str) -> str | None:
"""
网络请求函数:发起GET请求获取网页源码
:param target_url: 目标访问链接
:return: 网页HTML源码,请求异常返回None
"""
try:
# 超时时间10s,规避网络阻塞
response = requests.get(url=target_url, headers=HEADERS, timeout=10)
if response.status_code == 200:
response.encoding = response.apparent_encoding # 自适应编码,解决中文乱码
return response.text
else:
print(f"请求异常,响应状态码:{response.status_code}")
return None
except Exception as e:
print(f"网络请求报错:{str(e)}")
return None
def parse_news_list(html: str, target_keyword: str) -> list:
"""
列表页解析函数:提取新闻元数据并完成关键词过滤
:param html: 网页源码字符串
:param target_keyword: 筛选关键词
:return: 过滤后的新闻基础信息列表
"""
news_data = []
soup = BeautifulSoup(html, "html.parser")
# 定位新闻列表DOM节点,截取指定采集数量
news_item_list = soup.select(".news-item")[:MAX_COUNT]
for item in news_item_list:
try:
# 结构化提取节点数据
news_title = item.select_one("h3 a").get_text(strip=True)
news_link = item.select_one("h3 a")["href"]
news_time = item.select_one(".news-time").get_text(strip=True) if item.select_one(".news-time") else "未知发布时间"
news_source = item.select_one(".news-source").get_text(strip=True) if item.select_one(".news-source") else "未知媒体来源"
# 关键词匹配过滤
if target_keyword in news_title:
news_data.append({
"title": news_title, "link": news_link,
"publish_time": news_time, "source": news_source
})
except Exception:
# 跳过异常节点,保证爬虫持续运行
continue
return news_data
def parse_news_content(detail_link: str) -> str:
"""
详情页解析函数:提取并清洗新闻正文
:param detail_link: 新闻详情页链接
:return: 精简后正文摘要
"""
detail_html = get_html(detail_link)
if not detail_html:
return "正文数据获取失败"
soup = BeautifulSoup(detail_html, "html.parser")
# 通用正文p标签筛选
p_tags = soup.select("p")
raw_content = ""
for p in p_tags:
text = p.get_text(strip=True)
if len(text) > 10: # 过滤无效短文本、广告冗余文本
raw_content += text
# 正则清洗空白字符、换行符
clean_content = re.sub(r"\s+", "", raw_content)
return clean_content[:200] + "..." if len(clean_content) > 200 else clean_content
def save_csv(data_list: list, file_name: str):
"""
数据持久化函数:结构化写入CSV文件
:param data_list: 采集完成的新闻数据集
:param file_name: 存储文件名称
"""
# 定义标准化表头
csv_headers = ["序号", "新闻标题", "发布时间", "新闻来源", "正文摘要", "文章链接"]
# utf-8-sig编码兼容Excel中文显示
with open(file_name, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=csv_headers)
writer.writeheader()
# 遍历写入结构化数据
for idx, data in enumerate(data_list, 1):
writer.writerow({
"序号": idx, "新闻标题": data["title"], "发布时间": data["publish_time"],
"新闻来源": data["source"], "正文摘要": data["content"], "文章链接": data["link"]
})
print(f"\n✅ 数据采集完成,有效数据条数:{len(data_list)},存储路径:{file_name}")
def main_crawl():
"""爬虫主调度函数:整合全流程执行逻辑"""
print("=" * 50)
print(f"🚀 启动关键词定向爬虫 | 检索关键词:【{KEYWORD}】")
print("=" * 50)
# 1、获取首页源码
index_html = get_html(BASE_URL)
if not index_html:
print("❌ 首页请求失败,爬虫终止运行")
return
# 2、筛选关键词新闻
filter_news = parse_news_list(index_html, KEYWORD)
if not filter_news:
print(f"❌ 未检索到【{KEYWORD}】相关新闻数据")
return
print(f"🔍 初步筛选有效新闻:{len(filter_news)} 条,开始解析正文...")
# 3、批量采集正文
final_data = []
for news in filter_news:
news["content"] = parse_news_content(news["link"])
final_data.append(news)
print(f"✅ 采集完成:{news['title']}")
time.sleep(SLEEP_TIME)
# 4、数据本地化存储
save_csv(final_data, SAVE_FILE)
if __name__ == "__main__":
main_crawl()
4.2 代码分层技术解析
4.2.1 全局配置层
程序顶部封装全局静态参数,实现业务逻辑与配置解耦。开发者无需修改核心代码,仅调整参数即可更换爬取域名、检索关键词、采集上限,提升代码复用性与通用性。
4.2.2 网络请求层
get_html()函数为底层通用请求方法,集成异常捕获、状态码校验、编码自适应三大核心能力。通过apparent_encoding自动识别网页编码,从根源规避中文乱码问题;try-except异常捕获机制,防止网络波动导致程序崩溃。
4.2.3 数据解析层
程序采用CSS选择器完成DOM节点定位,相较于XPath语法更简洁、适配性更强。列表页解析实现新闻元数据提取,同时完成关键词初筛;详情页针对p标签通用正文结构进行文本采集,搭配正则表达式清洗空白、冗余符号,优化文本质量。
4.2.4 数据存储层
采用utf-8-sig编码格式写入CSV文件,解决Excel打开中文乱码痛点。数据按照标准化表头结构化存储,序号、标题、时间、摘要字段划分清晰,适配后期数据分析、数据入库处理。
5 程序运行测试与效果展示
5.1 运行部署方式
- 将代码保存为
news_crawler.py格式文件; - 自定义修改全局配置中的检索关键词、采集条数;
- 终端执行运行指令:
python news_crawler.py。
5.2 运行输出日志
程序运行后控制台实时打印采集状态,日志层级清晰,便于异常排查:
plain
==================================================
🚀 启动关键词定向爬虫 | 检索关键词:【人工智能】
==================================================
🔍 初步筛选有效新闻:15 条,开始解析正文...
✅ 采集完成:2025人工智能产业政策发布
✅ 采集完成:人工智能赋能制造业转型升级
✅ 数据采集完成,有效数据条数:15,存储路径:news_keyword_data.csv
5.3 数据输出结果
运行结束后在同级目录生成CSV文件,文件包含序号、新闻标题、发布时间、媒体来源、正文摘要、原文链接六大维度结构化数据,无冗余无效字段,满足轻量化数据分析需求。
6 性能优化与高阶扩展方案
6.1 反爬机制进阶优化
- 随机UA池:引入fake_useragent库动态生成浏览器请求头,固定UA容易被靶站风控识别;
- 代理IP池:高频采集场景下接入代理IP,规避单IP访问频率限制(推荐使用亿牛云爬虫代理IP)
- 动态渲染适配:针对JS异步加载新闻网站,替换Selenium、Playwright模拟浏览器渲染。
6.2 功能业务扩展
- 多关键词批量检索:改造关键词参数为列表格式,实现多词条并行过滤;
- 数据库持久化:将CSV存储替换为MySQL、MongoDB,适配海量新闻数据存储;
- 定时增量爬取:结合Schedule定时框架,实现每日定点增量采集,规避重复爬取。
6.3 采集性能优化
- 并发采集:采用aiohttp异步请求、Threading多线程提升采集速率;
- 数据去重:建立URL哈希池,过滤重复新闻链接,优化数据纯度。