欢迎光临
我们一直在努力

Python 实战2:新浪新闻静态 + 动态数据采集与清洗全流程

在大数据分析的工作中,数据采集是一切的基础,而实际的网页数据分为服务器端渲染的静态数据和接口动态加载的动态数据,二者的采集思路和方法差异显著。本次以新浪新闻为采集对象,用 Python 实现了单篇新闻静态正文 + 动态评论的全流程采集、解析、清洗与存储,全程整合Requests、BeautifulSoup、re、Pandas等核心库,下文分享完整的实现思路和代码细节。

一、技术栈与采集对象说明

1. 核心技术模块

本次采集从请求、解析、存储到预处理,各环节选用轻量且高效的 Python 库,各司其职又相互配合:

  • 请求模块:Requests库,模拟浏览器请求头,支持会话保持,适配静态页面和动态 API 请求;
  • 解析模块:BeautifulSoup4+re正则,前者解析结构化 HTML 提取静态内容,后者匹配 JS 代码中的隐藏参数;
  • 存储模块:Pandas库,将数据规整为 DataFrame,一键导出 CSV/TXT 格式,方便后续分析;
  • 预处理模块:Python 字符串方法 +BeautifulSoup文本提取,实现空白符、HTML 标签的快速清洗。

2. 采集对象

以新浪新闻(news.sina.com.cn)单篇新闻为目标,拆分两类采集内容:

  • 静态数据:新闻标题、发布信息、正文内容(服务器端渲染,直接嵌入 HTML 源码);
  • 动态数据:新闻下方的用户评论(通过独立 API 接口动态加载,需解析请求参数和返回的 JSON 数据)。

二、静态新闻数据采集:解析 HTML 源码

静态数据的核心是获取 HTML 并精准提取结构化内容,同时一个关键任务是从页面 JS 代码中提取动态评论 API 的调用参数,为后续采集评论做准备。

2.1 核心思路

  • 构造请求头(User-Agent、Referer、Cookie),用Requests获取新闻详情页 HTML;
  • 用BeautifulSoup解析 HTML,通过标签 / ID 选择器定位新闻标题、正文;
  • 用正则表达式匹配页面 JS 代码,提取调用评论 API 的核心参数(channel、newsid)。
  • 2.2 静态采集核心代码

    import requests
    import json
    import time
    import random
    import pandas as pd
    import re
    from bs4 import BeautifulSoup

    class SinaNewsRealScraper:
    """新浪新闻静态正文+动态评论采集器"""
    def __init__(self, news_url, cookie):
    self.news_url = news_url
    self.session = requests.Session()
    # 构造请求头,模拟浏览器行为
    self.session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
    "Cookie": cookie,
    "Referer": "https://news.sina.com.cn/"
    })

    def scrape_static_info(self):
    """采集新闻静态信息,提取标题、正文及评论API参数"""
    print(f"—开始采集新闻静态信息:{self.news_url}—")
    try:
    # 获取页面HTML
    response = self.session.get(self.news_url, timeout=20)
    response.raise_for_status() # 抛出请求异常
    # 自动识别编码,解决中文乱码
    response.encoding = response.apparent_encoding
    soup = BeautifulSoup(response.text, "lxml")

    # 提取新闻标题
    title = soup.find("h1", class_='main-title').text.strip()
    # 提取新闻正文
    article_body = soup.find("div", id='article')
    content = "\\n".join([p.text.strip() for p in article_body.find_all('p')])

    # 从JS代码中提取评论API的channel和newsid参数
    script_text = response.text
    channel_match = re.search(r"channel: '(\\w+)'", script_text)
    newsid_match = re.search(r"newsid: '(\\w+-[\\w]+)'", script_text)

    # 校验参数是否提取成功
    if not (channel_match and newsid_match):
    print("错误:未能在页面源码中找到API所需的channel和newsid参数。")
    return None

    # 整理API参数和静态信息
    api_params = {
    'channel': channel_match.group(1),
    'newsid': newsid_match.group(1)
    }
    static_info = {
    'title': title,
    'content': content,
    'api_params': api_params
    }
    print("静态信息及API参数采集成功!")
    return static_info

    except requests.RequestException as e:
    print(f"采集静态信息失败:{e}")
    return None
    except Exception as e:
    print(f"解析静态信息或提取参数时失败:{e}")
    return None

    三、动态评论数据采集:请求 API 接口

    新闻评论并非直接嵌入 HTML,而是通过前端 JS 调用 API 接口动态加载,因此核心是构造合法的 API 请求 URL,分页获取 JSON 数据并解析。

    3.1 核心思路

  • 利用静态采集得到的channel和newsid,拼接评论 API 的请求 URL;
  • 循环修改page参数实现分页请求,获取所有评论的 JSON 数据;
  • 解析 JSON 数据,提取评论用户名、发布时间、内容、地理位置等信息;
  • 对评论内容做简单清洗,规整为统一的字典格式。
  • 3.2 动态采集核心代码

    在上述SinaNewsRealScraper类中继续添加动态采集方法:

    def scrape_dynamic_comments(self, api_params):
    """采集动态评论数据,分页请求API接口"""
    all_comments = []
    page = 1
    # 分页请求,直到无新评论返回
    while True:
    try:
    # 构造评论API请求URL(新浪新闻评论API通用格式)
    comment_api = f"https://comment.sina.com.cn/page/info?version=1&format=json&channel={api_params['channel']}&newsid={api_params['newsid']}&page={page}"
    response = self.session.get(comment_api, timeout=20)
    response.raise_for_status()
    comment_data = json.loads(response.text)

    # 解析评论列表
    cmnt_list = comment_data.get('result', {}).get('data', {}).get('cmntlist', [])
    if not cmnt_list:
    print(f"第{page}页无评论,评论采集完成")
    break

    # 遍历评论,清洗并整理数据
    for cmnt in cmnt_list:
    comment = {
    'user_name': cmnt.get('nick', '匿名用户'),
    'location': cmnt.get('area', '未知地区'),
    'time': cmnt.get('time', ''),
    'content': cmnt.get('content', '').strip() # 去除空白符
    }
    all_comments.append(comment)

    print(f"第{page}页评论采集完成,共{len(cmnt_list)}条")
    page += 1
    # 随机休眠,避免请求过快被限制
    time.sleep(random.uniform(0.5, 1.5))

    except Exception as e:
    print(f"第{page}页评论采集失败:{e}")
    break
    return all_comments

    四、数据清洗与存储:规整并导出文件

    采集到的静态新闻信息和动态评论数据,需要统一清洗并存储为易读、易分析的格式,本次实现CSV(结构化数据)+TXT(纯文本) 双格式导出,兼顾后续数据分析和人工查看。

    4.1 核心思路

  • 对采集数据做最终校验,过滤空数据;
  • 用Pandas将评论数据转为 DataFrame,导出 CSV 文件(方便后续 NLP 分析);
  • 将新闻标题、正文与评论整合,按固定格式写入 TXT 文件(方便人工查看);
  • 处理文件写入异常,保证存储过程的稳定性。
  • 4.2 数据存储核心代码

    继续在类中添加保存方法,并实现主调用逻辑:

    def save_data(self, static_info, comments):
    """将采集数据保存为CSV(评论)和TXT(新闻+评论)"""
    if not static_info or not comments:
    print("无有效数据可保存")
    return
    print("\\n—开始保存文件—")
    # 保存评论为CSV文件
    try:
    df = pd.DataFrame(comments)
    csv_filename = 'sina_news_real.csv'
    df.to_csv(csv_filename, index=False, encoding='utf-8-sig')
    print(f"评论数据已成功保存到'{csv_filename}'")
    except Exception as e:
    print(f"保存CSV文件时出错:{e}")

    # 保存新闻+评论为TXT文件
    try:
    txt_filename = 'sina_news_real.txt'
    with open(txt_filename, 'w', encoding='utf-8') as f:
    f.write(f"新闻标题:{static_info['title']}\\n")
    f.write("="*40 + "\\n")
    f.write(f"新闻正文:\\n{static_info['content']}\\n\\n")
    f.write("="*40 + "\\n")
    f.write(f"用户评论(共{len(comments)}条):\\n")
    for comment in comments:
    f.write(f"—\\n用户:{comment['user_name']}({comment['location']})\\n")
    f.write(f"时间:{comment['time']}\\n内容:{comment['content']}\\n")
    print(f"新闻及评论数据已成功保存到'{txt_filename}'")
    except Exception as e:
    print(f"保存TXT文件时出错:{e}")

    # 主调用函数
    if __name__ == "__main__":
    # 替换为目标新闻URL和自己的新浪Cookie
    NEWS_URL = "https://news.sina.com.cn/s/2025-06-15/doc-imyfkzsy8999912.shtml"
    COOKIE = "你的新浪Cookie值"

    # 初始化采集器并执行采集
    scraper = SinaNewsRealScraper(NEWS_URL, COOKIE)
    static_info = scraper.scrape_static_info()
    if static_info:
    comments = scraper.scrape_dynamic_comments(static_info['api_params'])
    scraper.save_data(static_info, comments)
    print("—整个采集流程执行完毕—")

    五、采集结果与分析

    本次以新浪新闻《多地出现蜱虫伤人事件,严重可致死!医生提醒》为采集目标,最终实现了完整的数据采集:

  • 数据量:成功采集到新闻完整正文,以及 48 条有效用户评论,无缺失、无乱码;
  • 文件输出:生成新浪_news_real.csv和sina_news_real.txt两个文件,CSV 文件包含评论用户名、地理位置、时间、内容四列结构化数据,TXT 文件整合了新闻全文和评论,格式清晰;
  • 采集效率:分页请求加随机休眠,全程无请求被限制,采集 + 存储耗时约 10 秒。
  • 从采集结果也能发现一个行业现象:传统门户网站的用户互动数据量大幅减少,这与社交媒体、垂直 APP 的兴起相关,用户更倾向于在专属平台发表观点,门户网站的流量和粘性呈下降趋势。

    六、关键问题解决与实战技巧

    本次采集的核心难点是从页面 JS 代码中提取评论 API 的隐藏参数,这也是现代网页采集的常见痛点,分享解决方法和实战技巧:

  • JS 参数提取:将页面源码作为字符串,用正则表达式匹配变量名: '值'的固定模式,注意添加r前缀避免 Python 转义,精准捕获分组中的参数值;
  • 请求头构造:必须添加Cookie(新浪评论需要登录态)、Referer(模拟主站跳转),否则会被服务端拒绝请求;
  • 编码处理:使用response.apparent_encoding自动识别页面编码,解决新浪新闻 GBK/UTF-8 混合的中文乱码问题;
  • 反爬规避:分页请求时添加随机休眠(random.uniform),避免请求频率过高被 IP 限制;使用requests.Session()保持会话,减少连接建立开销;
  • 异常处理:对请求、解析、文件写入全环节做异常捕获,避免单个环节出错导致整个程序崩溃。
  • 七、应用前景与技术展望

    1. 实际应用前景

    本次采集的新闻正文和用户评论,是舆情分析、热点事件追踪、公众观点挖掘的优质数据源:

    • 对评论做情感分析,可判断公众对热点事件的正面 / 负面 / 中立态度;
    • 结合地理位置信息,分析不同地区用户的关注重点;
    • 对新闻正文和评论做关键词提取,挖掘事件的核心讨论点。这些分析结果可应用于新闻传播学研究、市场营销、公共政策制定等领域。

    2. 技术优化与展望

    本次实现的是单篇新闻的采集,后续可从以下方面优化,实现规模化采集:

  • 增加新闻列表爬取模块,遍历新浪新闻栏目,实现多新闻自动采集;
  • 添加IP 代理池和Cookie 池,解决大规模采集的反爬限制;
  • 整合多进程 / 多线程,提高批量采集的效率;
  • 增加数据去重、关键词过滤等预处理功能,提升数据质量;
  • 将采集结果存入 MySQL/MongoDB 数据库,替代本地文件,支持大数据量存储。
  • 八、实战总结

    本次实战完成了从静态 HTML 解析到动态 API 请求的全流程网页采集,核心收获有两点:

  • 现代网页的数据来源是多样化的,不能仅局限于 HTML 标签,必须具备前端代码分析能力,能从 JS、API 接口中找到数据线索;
  • Python 数据采集的核心是库的灵活组合和细节的把控,请求头的构造、编码的处理、反爬的规避,每一个细节都决定采集的成败。
  • 赞(0)
    未经允许不得转载:171主机测评 » Python 实战2:新浪新闻静态 + 动态数据采集与清洗全流程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址