新闻爬虫开发实战:Python 搞定新闻网站关键词文章抓取

1 引言

在大数据与数字化信息快速迭代的行业背景下,新闻文本数据是舆情监测、行业研判、舆情风控、资讯聚合领域的核心数据源。传统人工采集方式存在采集效率低、数据维度单一、时效性差、人力成本高等痛点,无法满足规模化、精准化的数据采集需求。

Python 凭借轻量化的语法特性、成熟的爬虫生态库、丰富的数据处理工具,成为轻量化定向爬虫开发的首选编程语言。本文基于 Requests+BeautifulSoup 技术栈,搭建一款结构化关键词定向新闻爬虫,实现新闻资讯定向抓取、文本解析、关键词过滤、本地化持久化存储。文章从技术原理、环境部署、代码分层实现、逻辑解析、优化方案多角度展开,完整落地新闻爬虫开发流程,适用于技术开发者、数据分析从业者入门学习,所有代码可直接编译运行。

2 技术栈与开发环境搭建

2.1 核心技术栈选型

本次爬虫采用静态网页爬虫方案,适配主流新闻门户网站静态渲染页面,技术栈精简且稳定性高,各组件分工明确:

  • 网络请求库 Requests:模拟HTTP/HTTPS协议发起网络请求,替代原生urllib库,支持自定义请求头、超时配置、编码自适应,适配绝大多数静态网页请求场景。
  • 网页解析库 BeautifulSoup4:基于HTML/XML文档解析引擎,通过CSS选择器完成DOM节点定位,实现结构化数据提取,相较于正则表达式,容错率更高、代码可读性更强。
  • 数据存储模块 CSV:轻量化文本存储格式,兼容Excel、数据库、数据分析工具,无需额外部署环境,适合中小型量级新闻数据持久化。
  • 辅助工具库:time库实现请求休眠防封禁;re正则库完成文本清洗、冗余字符过滤。

2.2 爬虫合规与风控规范

爬虫开发必须遵循行业合规准则与网络安全法规,规避法律风险与服务器风控限制:

  1. 遵循网站 robots.txt 协议,仅爬取公开非授权加密的公共资讯数据;
  2. 设置请求休眠间隔,控制请求频率,规避高频访问造成的服务器负载压力;
  3. 禁止篡改请求参数、恶意高频爆破爬取,本文代码仅用于技术学习与科研分析。

3 新闻爬虫架构设计与核心原理

3.1 整体架构流程

本爬虫采用分层模块化设计,将请求、解析、筛选、存储逻辑解耦,降低代码耦合度,便于后期迭代优化。整体执行流程分为四大核心模块:

  1. 网络请求层:携带伪装请求头向目标域名发起GET请求,获取网页原始HTML源码;
  2. 数据解析层:通过DOM节点筛选,提取新闻标题、发布时间、源站链接、媒体来源等元数据;
  3. 关键词过滤层:基于字符串匹配规则,筛选含目标关键词的有效新闻数据,剔除冗余资讯;
  4. 持久化存储层:清洗正文文本,结构化录入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 运行部署方式

  1. 将代码保存为 news_crawler.py 格式文件;
  2. 自定义修改全局配置中的检索关键词、采集条数;
  3. 终端执行运行指令: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哈希池,过滤重复新闻链接,优化数据纯度。
相关推荐
m0_733565461 小时前
怎么对MongoDB数据进行批量部分更新_BulkWrite机制与性能优化
jvm·数据库·python
m0_463672201 小时前
如何理解闭包对内存的影响并手动解除引用防止泄漏
jvm·数据库·python
weiabc1 小时前
整数最接近等因数分解函数(汇编优化版)
开发语言·前端·javascript
Highcharts.js1 小时前
专为软件团队打造的数据可视化开发工具|Highcharts图表
开发语言·信息可视化·highcharts·实战代码
yuanpan1 小时前
Python + sqlite3 本地 SQLite 数据库操作实战:完整 CRUD 入门教程
开发语言·python·opencv
rit84324991 小时前
水声通信Rake接收机-MATLAB
开发语言·matlab
sindyra1 小时前
享元模式(Flyweight Pattern)
java·开发语言·设计模式·享元模式·优缺点
NG WING YIN1 小时前
一鍵計算稅項支出
python