Python 爬虫项目:新闻资讯全站爬虫(分页 + 栏目 + 增量抓取)
前言新闻资讯网站是时政、行业、科技、娱乐、财经等各类信息的核心发布载体海量实时新闻数据可用于舆情监测、行业热点分析、内容聚合、资讯归档、文本挖掘等场景。传统人工浏览、复制归档的方式无法应对海量资讯、多栏目、持续更新的内容特性且难以做到定时抓取、增量更新与统一结构化管理。借助 Python 爬虫技术可自动化遍历新闻站点全栏目、全分页内容抓取标题、发布时间、作者、来源、正文、标签、阅读量等字段完成清洗、分类存储并实现增量抓取避免重复采集大幅提升资讯数据整理与分析效率。本文以综合类新闻资讯站点为实战对象覆盖栏目遍历、分页爬取、新闻详情解析、多类型文本清洗、重复数据过滤、增量更新、日志记录等核心功能同时针对新闻站常见的基础反爬、正文分段、广告干扰、动态分页等问题给出解决方案。项目所用库及官方文档链接 Python 官方标准库、requests、BeautifulSoup、lxml、re 正则库、csv、json、os、time、random、fake-useragent、logging 日志库。全文采用模块化开发代码解耦度高、可维护性强适配绝大多数传统静态新闻网站仅修改标签规则与 URL 即可快速迁移至行业资讯、自媒体专栏、地方新闻等同类站点。所有代码经过实测具备完善异常捕获与防爬策略适合长期稳定运行。一、项目整体规划与环境准备1.1 业务场景与采集字段主流新闻站结构首页 → 分类栏目页 → 新闻列表分页 → 新闻详情页。 本次统一采集字段栏目名称、新闻标题、发布时间、作者 / 来源、阅读量、新闻标签、正文内容、详情链接、抓取时间。 业务目标分为三层基础功能单栏目分页新闻抓取进阶功能全站多栏目自动遍历抓取高阶功能增量抓取、去重、日志监控、定时更新。所有数据均为网站公开展示内容采集严格遵循站点 robots 协议与网络安全法规合理控制访问频率。1.2 依赖库说明与安装表格库名称类型核心用途requests第三方发送 HTTP 请求获取页面源码BeautifulSouplxml第三方解析 HTML 标签提取文本与链接fake-useragent第三方随机 UA 伪装绕过基础拦截re标准库清洗正文、过滤广告、匹配时间与数字csv/os标准库文件创建、数据读写、路径判断time/random标准库随机延时、时间格式化、防高频访问logging标准库运行日志、异常记录、任务监控安装命令bash运行pip install requests beautifulsoup4 lxml fake-useragent1.3 页面结构与反爬分析页面层级首页提取所有栏目链接 → 栏目页多分页展示新闻列表 → 列表项跳转至详情页查看完整正文数据特征列表页展示标题、摘要、时间、阅读量详情页存放完整正文、作者、标签正文多分段、夹杂广告、推荐阅读等冗余内容反爬特征校验 UA、限制单 IP 访问频率无验证码与加密参数设置随机延时 请求头即可稳定抓取分页规则URL 携带page页码参数页码从 1 递增。1.4 模块化架构设计请求模块统一请求、异常捕获、编码处理、请求头封装文本清洗模块清理空白、广告、无关链接、冗余符号链接提取模块栏目链接、新闻列表链接、分页链接提取解析模块列表页解析、详情页正文解析去重 增量模块基于 URL 判断重复实现增量抓取存储模块CSV 持久化自动创建文件与表头日志模块记录运行状态、成功数、异常信息调度模块程序入口串联全流程控制栏目与分页遍历。二、基础模块封装公共函数2.1 全局配置与日志初始化python运行import requests from bs4 import BeautifulSoup from fake_useragent import UserAgent import re import csv import os import time import random import logging # 全局配置 ua UserAgent() BASE_DOMAIN https://news.example.com SAVE_FILE 新闻资讯数据.csv # 延时范围 MIN_SLEEP 1.5 MAX_SLEEP 3.5 # 日志配置 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[logging.FileHandler(spider_log.log, encodingutf-8)] ) logger logging.getLogger(__name__)2.2 通用网络请求函数python运行def get_html(url): 通用GET请求返回页面源码 headers { User-Agent: ua.random, Accept: text/html,application/xhtmlxml,application/xml;q0.9, Accept-Language: zh-CN,zh;q0.9 } try: resp requests.get(url, headersheaders, timeout15) resp.encoding utf-8 if resp.status_code 200: return resp.text else: logger.warning(f请求失败状态码{resp.status_code} | URL: {url}) return None except Exception as e: logger.error(f网络异常{str(e)} | URL: {url}) return None2.3 通用文本清洗函数python运行def clean_text(text): 基础清洗空白、换行、制表符 if not text: return text re.sub(r[\n\r\t], , text.strip()) text re.sub(r\s, , text) return text def filter_ad_content(text): 进阶清洗过滤广告、推荐阅读、二维码文字 ad_patterns [ r点击.*, r推荐阅读.*, r扫码关注.*, r本文来源.*广告, r编辑.*责编.* ] for pat in ad_patterns: text re.sub(pat, , text) return clean_text(text)2.4 CSV 数据存储函数python运行def save_to_csv(data_list): 批量写入CSV自动创建表头 header [ 栏目名称, 新闻标题, 发布时间, 来源作者, 阅读量, 新闻标签, 正文内容, 详情链接, 抓取时间 ] file_exist os.path.exists(SAVE_FILE) with open(SAVE_FILE, a, encodingutf-8-sig, newline) as f: writer csv.DictWriter(f, fieldnamesheader) if not file_exist: writer.writeheader() writer.writerows(data_list)2.5 随机延时函数python运行def random_sleep(): sleep_time random.uniform(MIN_SLEEP, MAX_SLEEP) time.sleep(sleep_time)三、基础实战单栏目分页新闻抓取实现单个新闻栏目全分页列表抓取 详情页正文解析。3.1 页面标签定位说明列表页栏目新闻条目classnews-item标题链接、发布时间、阅读量、来源均在条目内部详情页标题classarticle-title发布信息classarticle-meta正文容器classarticle-content标签位于classarticle-tag。3.2 列表页解析 提取详情链接python运行def parse_news_list(html, column_name): 解析新闻列表页返回(标题、时间、来源、阅读量、详情链接)列表 news_links [] soup BeautifulSoup(html, lxml) items soup.find_all(div, class_news-item) for item in items: a_tag item.find(a) if not a_tag or not a_tag.get(href): continue title clean_text(a_tag.get_text()) link a_tag.get(href) # 拼接完整链接 if link.startswith(/): link BASE_DOMAIN link # 发布时间 time_tag item.find(span, class_pub-time) pub_time clean_text(time_tag.get_text()) if time_tag else # 来源/作者 source_tag item.find(span, class_source) source clean_text(source_tag.get_text()) if source_tag else # 阅读量 view_tag item.find(span, class_view-num) view clean_text(view_tag.get_text()) if view_tag else news_links.append({ column: column_name, title: title, pub_time: pub_time, source: source, view: view, link: link }) return news_links3.3 新闻详情页解析函数python运行def parse_news_detail(html): 解析详情页标签、正文 soup BeautifulSoup(html, lxml) # 新闻标签 tag_box soup.find(div, class_article-tag) tags clean_text(tag_box.get_text()) if tag_box else # 正文 content_box soup.find(div, class_article-content) content if content_box: content filter_ad_content(content_box.get_text()) return tags, content3.4 单栏目分页抓取主函数python运行def crawl_single_column(column_name, column_url, max_page5): 单栏目全分页抓取 logger.info(f开始抓取栏目{column_name}) all_news [] for page in range(1, max_page 1): page_url f{column_url}?page{page} logger.info(f正在访问分页{page_url}) html get_html(page_url) if not html: random_sleep() continue # 解析列表 news_list parse_news_list(html, column_name) if not news_list: logger.info(f第{page}页无新闻数据) random_sleep() continue # 遍历每条新闻访问详情 for news in news_list: detail_html get_html(news[link]) if not detail_html: continue news_tags, news_content parse_news_detail(detail_html) # 组装完整数据 data { 栏目名称: news[column], 新闻标题: news[title], 发布时间: news[pub_time], 来源作者: news[source], 阅读量: news[view], 新闻标签: news_tags, 正文内容: news_content, 详情链接: news[link], 抓取时间: time.strftime(%Y-%m-%d %H:%M:%S) } all_news.append(data) random_sleep() random_sleep() # 批量存储 if all_news: save_to_csv(all_news) logger.info(f栏目 {column_name} 抓取完成共{len(all_news)}条新闻) else: logger.warning(f栏目 {column_name} 未采集到有效数据) if __name__ __main__: # 测试单栏目 test_column 科技资讯 test_url https://news.example.com/tech crawl_single_column(test_column, test_url, max_page3)四、进阶实战全站多栏目自动抓取4.1 提取首页所有栏目链接python运行def get_all_column_links(home_url): 从首页提取全部栏目名称链接 column_list [] html get_html(home_url) if not html: return column_list soup BeautifulSoup(html, lxml) column_box soup.find(div, class_nav-column) a_tags column_box.find_all(a) for a in a_tags: col_name clean_text(a.get_text()) col_href a.get(href) if not col_name or not col_href: continue if col_href.startswith(/): col_href BASE_DOMAIN col_href column_list.append((col_name, col_href)) return column_list4.2 全站抓取调度函数python运行def crawl_all_news(home_url, page_per_column3): 遍历全站所有栏目执行抓取 logger.info( 全站新闻爬虫启动 ) columns get_all_column_links(home_url) if not columns: logger.error(未获取到任何栏目链接任务终止) return logger.info(f共识别到 {len(columns)} 个栏目) for col_name, col_url in columns: crawl_single_column(col_name, col_url, page_per_column) random_sleep() logger.info( 全站抓取任务全部结束 ) if __name__ __main__: home_page https://news.example.com crawl_all_news(home_page, page_per_column2)五、高阶功能去重与增量抓取新闻站持续更新重复抓取会产生大量冗余数据通过记录已抓取 URL实现增量更新。5.1 读取历史已抓取链接python运行def get_exist_links(): 从CSV读取已抓取的新闻链接用于去重 exist_links set() if not os.path.exists(SAVE_FILE): return exist_links with open(SAVE_FILE, r, encodingutf-8-sig) as f: reader csv.DictReader(f) for row in reader: link row.get(详情链接, ) if link: exist_links.add(link) return exist_links5.2 改造增量抓取逻辑核心片段在遍历新闻详情前增加判断python运行exist_links get_exist_links() # 原有循环内添加 if news[link] in exist_links: logger.info(f已存在跳过{news[title]}) continue每次运行仅抓取新增新闻实现长期定时增量更新。六、异常处理、优化方案与拓展方向6.1 常见问题排查表格问题现象解决方案正文混入广告、推荐内容补充正则规则过滤无关文本中文乱码统一使用utf-8请求、utf-8-sig存储频繁 403 拦截增大随机延时区间、更换 UA链接相对路径访问失败统一拼接根域名6.2 性能与稳定性优化断点续爬记录当前栏目与分页位置中断后继续执行异步抓取引入aiohttp提升并发速度代理 IP 池大规模抓取时轮换 IP防止封禁分文件存储按栏目 / 日期拆分 CSV避免单文件过大。6.3 功能拓展定时任务结合schedule库实现每日定时自动爬取关键词筛选只抓取包含指定关键词的新闻用于舆情监控文本分词结合 jieba 分词做热点词统计数据库存储对接 MySQL/Redis支撑大数据量检索。七、项目总结本项目完整实现了新闻资讯网站单栏目、多栏目、全分页、详情解析、文本清洗、去重增量、日志监控全套爬虫能力覆盖资讯类站点主流页面结构与数据场景。代码分层清晰、模块独立学习与落地兼顾。技术要点汇总静态页面多级遍历、链接拼接、复杂文本清洗、广告过滤、基于 URL 的数据去重、增量抓取、日志运维、延时防爬。该套架构可无缝迁移至行业资讯、财经快讯、体育娱乐、自媒体专栏等同类站点。