恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

个人新闻中枢:静态站点+定制爬虫构建可审计信息过滤系统

  • 首页
  • 资讯中心
  • /
  • 个人新闻中枢:静态站点+定制爬虫构建可审计信息过滤系统

相关资讯

UWB定位与SLAM融合实战:从测距原理到室内机器人部署避坑指南 2026/10/20 23:57:44
AI绘图与AI视频入门指南:从底层原理到工程化实践 2026/10/20 23:57:44
加密流量分析实战:TLS解密兼容性问题排查指南 2026/10/20 23:52:43

最新资讯

从零搭建代码评审自动化流水线:开源工具链选型与实操
Pod多容器资源共享:从Linux Namespace到Sidecar实战
深入理解PostgreSQL Hybrid Hash Join:批次、内存与SQL调优
大模型推理性能优化:Prefill与Decode瓶颈及KV缓存显存管理
NGS分析必看:Conda与Mamba环境配置及生物信息工具安装指南
Java开发者如何正确转型大模型?两条高价值路径详解

今日推荐

SAP 屏幕上的金额未必存在数据库表里,从 WB2R_SV 的 Net Amount 看懂运行时计算
具身智能中‘指哪打哪’的视觉语言动作联合建模
AI时代人工翻译技术博客的价值与实践指南

本周热门

基于GMM的语音识别系统原理与MATLAB实现详解
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

个人新闻中枢:静态站点+定制爬虫构建可审计信息过滤系统

发布时间:2026/10/20 23:57:44
个人新闻中枢:静态站点+定制爬虫构建可审计信息过滤系统 简介这是一套轻量级个人新闻收集网站网页模板面向零基础或入门级前端学习者、个人博客爱好者及内容聚合需求者帮助用户无需编程即可快速搭建美观实用的资讯展示站点。资源共13个文件含1个核心HTML主页index.htm、5个图像资源4张JPG1张GIF用于装饰元素、3个GIF动效图标、2个INI系统配置文件、1个URL快捷方式及1个TXT说明文档整体仅24KB便于下载部署与本地调试。已有157人学习下载适合希望快速上手响应式布局、理解静态网站结构、实践内容替换与主题微调的学习者。用户可直接编辑index.htm更新新闻条目通过images文件夹更换配图依据ReadMe.txt完成基础配置模板已预设SEO元信息、适配多端的CSS样式及简洁图文混排结构开箱即用是入门网页定制与信息聚合实践的理想范例。1. 个人新闻收集网站模板不是博客也不是 RSS 聚合器而是你自己的「信息过滤中枢」“个人新闻收集网站模板”这个标题常被误读成「做个带新闻栏的个人主页」或「用 WordPress 搭个资讯站」——但真正落地时你会发现它既不依赖第三方 API 频繁失效也不靠人工点开几十个链接再复制粘贴它的核心价值是把散落在不同信源政府公报、行业白皮书、开源项目更新页、技术社区公告、学术预印本平台里的结构化增量信息以你定义的关键词、时间窗口、可信度权重和去重粒度自动抓取、清洗、归类、存档并生成可订阅、可检索、可回溯的静态站点。它不是替代新闻 App而是解决「我关心的 A 领域政策变动」「B 技术栈的 CVE 更新」「C 行业协会季度报告」这类长尾、低频、高精度需求的最小可行闭环。适合某高校科研组跟踪政策动向、某公司技术委员会做竞品动态归档、或独立开发者构建自己的知识基座。它不追求实时性但要求可验证、可审计、可离线导出——这才是“模板”的真实分量。2. 为什么选静态生成 定制爬虫 本地索引避开云服务陷阱与 API 黑箱2.1 不用 CMS 或 SaaS 平台的三个硬理由很多新手第一反应是“用 Ghost / Hexo / Notion 搭一个”但很快会撞墙内容主权失控Notion 的 RSS 导出只含摘要且无法控制字段映射比如把「发布机构」强制映射为 YAML front matter 中的source_org更新不可审计WordPress 插件拉取的 RSS 源一旦变更格式如pubDate改成date全站历史条目时间戳集体错乱却无日志可查长期存档失效SaaS 平台若关闭服务如某知名聚合工具 2023 年下线你积累两年的元数据、分类标签、阅读状态全部清零。提示所谓“模板”本质是把「信息采集逻辑」和「呈现逻辑」彻底解耦——采集脚本输出标准 JSONL每行一个新闻条目渲染模板只消费该 JSONL。二者可独立升级、测试、备份。2.2 静态站点生成器SSG的不可替代性我们最终选定Hugo而非 Jekyll 或 Next.js作为渲染层原因直击痛点零运行时依赖生成的纯 HTML/CSS/JS 可直接扔进任何对象存储如阿里云 OSS、腾讯云 COS或 Git 仓库 Pages无需 Node.js 环境或数据库毫秒级全文搜索Hugo 内置lunr.js支持客户端搜索且可导出search-index.json供自定义前端调用避免 Algolia 等第三方搜索服务的隐私与成本问题原生支持多语言内容路由当需要按「中文政策原文」和「英文技术公告」分频道展示时Hugo 的multilingual模块只需配置languageCode zh和contentDir content/zh无需改代码。2.3 爬虫层必须自己写为什么 Requests BeautifulSoup 是当前最稳组合有人提议用 Scrapy但对个人场景是过度设计Scrapy 需维护settings.py、pipelines.py、middlewares.py三套配置而实际需求只是「从 5 个固定 URL 解析h1标题、time时间、p首段」当目标网站反爬升级如增加 JS 渲染Scrapy 的Splash集成复杂度陡增而 Requests fake-useragenttime.sleep()组合配合retrying库重试反而更易调试。我们采用「单文件爬虫脚本」fetch_news.py核心逻辑仅 87 行关键设计如下# fetch_news.py import requests from bs4 import BeautifulSoup from datetime import datetime, timedelta import json import time from fake_useragent import UserAgent def fetch_from_source(url: str, selector_map: dict) - list: 从单个源抓取返回标准化字典列表 headers {User-Agent: UserAgent().random} try: resp requests.get(url, headersheaders, timeout10) resp.raise_for_status() soup BeautifulSoup(resp.text, html.parser) items [] for item in soup.select(selector_map[item]): # 强制提取字段缺失则设为 None后续清洗阶段统一处理 title item.select_one(selector_map[title]).get_text(stripTrue) if item.select_one(selector_map[title]) else None pub_time item.select_one(selector_map[time]).get_text(stripTrue) if item.select_one(selector_map[time]) else None link item.select_one(selector_map[link])[href] if item.select_one(selector_map[link]) and item.select_one(selector_map[link]).has_attr(href) else None items.append({ title: title, pub_time: pub_time, link: link, source_url: url, fetched_at: datetime.now().isoformat(), id: f{url.split(//)[1].split(/)[0]}_{hash(link or title)[:8]} # 基于域名链接哈希生成稳定 ID }) return items except Exception as e: print(f[ERROR] Failed to fetch {url}: {e}) return [] # 主流程遍历配置好的信源列表 sources [ { url: https://www.xxx.gov.cn/xxgk/tzgg/, selector: { item: .list-item, title: h4 a, time: .date, link: h4 a } }, { url: https://github.com/tensorflow/tensorflow/releases, selector: { item: .Box-row, title: h2 a, time: relative-time, link: h2 a } } ] all_news [] for src in sources: print(fFetching from {src[url]}...) all_news.extend(fetch_from_source(src[url], src[selector])) time.sleep(2) # 礼貌性间隔避免触发风控 # 去重按 id 字段保留最新一条因同一新闻可能在多个源出现 seen_ids set() deduped [] for item in sorted(all_news, keylambda x: x.get(fetched_at, ), reverseTrue): if item[id] not in seen_ids: seen_ids.add(item[id]) deduped.append(item) # 输出为 JSONL每行一个 JSON 对象供 Hugo 消费 with open(data/news.jsonl, w, encodingutf-8) as f: for item in deduped: f.write(json.dumps(item, ensure_asciiFalse) \n)这段代码的关键设计说明id字段用f{domain}_{hash(link)[:8]}生成确保同一新闻在不同源重复抓取时能被精准去重且不依赖外部数据库fetched_at记录抓取时间而非发布时间用于判断「本次抓取是否覆盖了上次遗漏的条目」selector_map将 CSS 选择器与字段绑定新增信源只需在sources列表里加一项无需改函数逻辑所有异常捕获后继续执行单个源失败不影响其他源符合「个人项目容错优先」原则。3. Hugo 模板如何把 JSONL 渲染成可搜索、可归档、可 RSS 订阅的静态站3.1 数据层用 Hugo 的data目录桥接爬虫与渲染Hugo 默认不直接读取 JSONL但我们通过一个轻量转换脚本jsonl_to_hugo_data.py将data/news.jsonl转为data/news.json标准 JSON 数组# jsonl_to_hugo_data.py import json with open(data/news.jsonl, r, encodingutf-8) as f: lines [json.loads(line.strip()) for line in f if line.strip()] # 按日期分组生成 Hugo data 结构 grouped {} for item in lines: # 提取年月如 2024-03-15 → 2024/03 date_str item.get(pub_time, ) if not date_str: continue try: dt datetime.fromisoformat(date_str.replace(Z, 00:00)) if T in date_str else datetime.strptime(date_str, %Y-%m-%d) year_month f{dt.year}/{dt.month:02d} except: year_month unknown if year_month not in grouped: grouped[year_month] [] grouped[year_month].append(item) # 写入 data/news.jsonHugo 可直接 .Site.Data.news 访问 with open(data/news.json, w, encodingutf-8) as f: json.dump(grouped, f, ensure_asciiFalse, indent2)注意此脚本在每次fetch_news.py运行后自动执行可用 Makefile 或 GitHub Actions 触发确保 Hugo 构建时data/news.json总是最新的。3.2 页面结构按「时间轴 分类 全文搜索」三维组织我们在layouts/_default/list.html中定义主页面逻辑!-- layouts/_default/list.html -- {{ define main }} div classcontainer h1我的新闻中枢/h1 !-- 搜索框调用 lunr.js -- div classsearch-box input typetext idsearch-input placeholder搜索标题、来源、关键词... / div idsearch-results/div /div !-- 时间轴归档按年月折叠 -- div classarchive {{ range $year_month, $items : .Site.Data.news }} details summary{{ $year_month }} ({{ len $items }} 条)/summary ul {{ range $items }} li a href{{ .link }} target_blank{{ .title | truncate 60 }}/a small classsource[{{ .source_url | replaceRE https?://([^/]).* $1 }}]/small small classtime{{ .pub_time | time.Format :date_long }}/small /li {{ end }} /ul /details {{ end }} /div /div !-- lunr.js 搜索初始化 -- script // 从 /index.json 加载全文索引Hugo 自动生成 fetch(/index.json).then(r r.json()).then(indexData { const idx lunr(function () { this.ref(id) this.field(title, { boost: 10 }) this.field(source_url) this.field(pub_time) indexData.forEach(function (doc) { this.add(doc) }, this) }) const input document.getElementById(search-input) const results document.getElementById(search-results) input.addEventListener(input, function () { const query this.value.trim() if (!query) return const res idx.search(query) results.innerHTML res.map(r { const doc indexData.find(d d.id r.ref) return div classsearch-resulta href${doc.link} target_blank${doc.title}/abrsmall${doc.source_url}/small/div }).join() }) }) /script {{ end }}关键参数说明index.json是 Hugo 在构建时自动生成的全文索引文件需在config.toml中启用buildSearchIndex truelunr.js的boost: 10给标题字段更高权重确保搜「Transformer」时标题含该词的条目排在前面details/summary实现可折叠时间轴避免页面过长移动端友好。3.3 RSS 订阅用 Hugo 的内置 RSS 模板生成合规 Feed在layouts/_default/rss.xml中{{ printf ?xml version\1.0\ encoding\utf-8\? | safeHTML }} rss version2.0 xmlns:atomhttp://www.w3.org/2005/Atom channel title{{ .Site.Title }}/title link{{ .Site.BaseURL }}/link description{{ .Site.Params.description }}/description generatorHugo {{ .Hugo.Version }}/generator lastBuildDate{{ now.Format Mon, 02 Jan 2006 15:04:05 -0700 | safeHTML }}/lastBuildDate atom:link href{{ .Site.BaseURL }}index.xml relself typeapplication/rssxml / {{ range first 20 .Site.Data.news }} {{ range . }} item title{{ .title | htmlUnescape }}/title link{{ .link }}/link guid{{ .link }}/guid pubDate{{ .pub_time | time.Format Mon, 02 Jan 2006 15:04:05 -0700 | safeHTML }}/pubDate description{{ .title | plainify | truncate 200 }}/description /item {{ end }} {{ end }} /channel /rss提示RSS 的guid必须全局唯一且不变我们直接复用爬虫生成的id字段但此处用.link更稳妥因部分源无稳定 IDpubDate严格按 RFC 822 格式避免某些 RSS 阅读器解析失败。4. 避坑爬虫失效、时间解析错乱、搜索结果为空的 5 个血泪现场4.1 现象爬虫跑着跑着突然全源返回空列表日志只显示[ERROR] Failed to fetch xxx: ReadTimeout原因目标网站启用了 Cloudflare 的「Under Attack Mode」对非浏览器请求返回 503而fake-useragent生成的 UA 已被大量爬虫滥用被 Cloudflare 列入黑名单。解决不用fake-useragent改用一组手动维护的、经测试有效的 UA 字符串池并加入Accept-Language和Accept-Encoding头VALID_UAS [ Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15 ] headers { User-Agent: random.choice(VALID_UAS), Accept-Language: zh-CN,zh;q0.9,en;q0.8, Accept-Encoding: gzip, deflate }4.2 现象某政府网站的时间字段解析出来是「2024年3月15日」但 Hugo 的time.Format报错parsing time 2024年3月15日原因Hugo 的time.Format只支持 Go 的标准时间格式如2006-01-02不识别中文日期。爬虫层未做标准化。解决在fetch_news.py中增加日期归一化函数统一转为 ISO 格式def parse_chinese_date(date_str: str) - str: 将 2024年3月15日 转为 2024-03-15 import re match re.match(r(\d{4})年(\d{1,2})月(\d{1,2})日, date_str) if match: y, m, d match.groups() return f{y}-{int(m):02d}-{int(d):02d} return date_str # 原样返回交由后续逻辑处理 # 在 fetch_from_source 中调用 pub_time parse_chinese_date(pub_time_raw)4.3 现象搜索框输入关键词search-results区域始终空白控制台无报错原因index.json文件未生成或路径错误。Hugo 默认只对content/下的 Markdown 文件生成索引而我们的数据来自data/目录。解决在config.toml中显式配置buildSearchIndex true并确保index.json路径正确[outputs] home [HTML, RSS, JSON] # 关键必须包含 JSON [outputFormats.JSON] mediaType application/json baseName index isPlainText true notAlternative true这样 Hugo 会在根目录生成/index.json与模板中fetch(/index.json)路径一致。4.4 现象GitHub Releases 页面抓取到的time标签内容是相对时间如about 2 hours ago无法解析为绝对时间原因GitHub 使用relative-time自定义元素其datetime属性才是 ISO 时间但BeautifulSoup默认不读取属性值。解决修改选择器优先读取datetime属性# 原 selector_map[time] relative-time # 改为 time_elem item.select_one(relative-time) or item.select_one(time) pub_time time_elem.get(datetime) or time_elem.get_text(stripTrue) if time_elem else None4.5 现象Hugo 构建成功但访问页面时时间显示为0001-01-01原因.pub_time字段在 JSON 中为nullHugo 的time.Format遇到空值会回退到零值时间。解决在模板中增加空值保护{{ if .pub_time }} small classtime{{ .pub_time | time.Format :date_long }}/small {{ else }} small classtime时间未知/small {{ end }}5. 进阶技巧用 Git 版本控制实现新闻溯源、变更比对与一键回滚5.1 为什么必须用 Git 管理data/news.jsonl新闻数据不是「一次生成永久有效」而是持续演进的某条政策原文链接失效下次抓取时link字段变为空但你仍需保留旧版记录某技术文档更新后标题微调如「v2.3.0 发布」→「v2.3.0 正式版发布」你需知道何时发生变更同事想查看「上个月我漏掉了哪些条目」需对比两个时间点的数据快照。Git 天然提供这些能力且无需额外数据库。5.2 自动化工作流每次抓取后提交带语义的 Commit我们用git_commit_after_fetch.sh脚本封装提交逻辑#!/bin/bash # git_commit_after_fetch.sh set -e # 生成本次抓取的摘要 NEW_COUNT$(wc -l data/news.jsonl | awk {print $1}) OLD_COUNT$(git ls-tree -r HEAD -- data/news.jsonl | awk {print $3} | xargs git show | wc -l | awk {print $1}) # 提交消息包含新增/删除数及抓取时间 git add data/news.jsonl git commit -m news: update $(date %Y-%m-%d %H:%M) | $((NEW_COUNT-OLD_COUNT)) entries提示git ls-tree -r HEAD -- data/news.jsonl获取上一版news.jsonl的 blob hash再用git show输出内容行数从而计算净增量。5.3 用 Git Diff 快速定位新闻变更当需要排查「为什么某条新闻消失了」直接运行# 查看最近 3 次提交中 news.jsonl 的变化 git log -3 --prettyformat:%h %ad %s --dateshort -- data/news.jsonl # 对比当前版与上一版只显示新增和删除的 ID即新闻条目标识 git diff HEAD~1 HEAD -- data/news.jsonl | grep -E ^\|^-输出类似-{id:gov_cn_abc123,title:关于XXX的通知,pub_time:2024-03-10,...} {id:gov_cn_def456,title:关于YYY的补充通知,pub_time:2024-03-15,...}一眼可知旧条目gov_cn_abc123被移除可能源已下线新条目gov_cn_def456被加入。5.4 一键回滚到任意历史状态若某次抓取引入了大量垃圾数据如某个信源被黑页面注入广告链接可立即恢复# 查看所有包含 news: 的提交 git log --grepnews: --oneline # 回滚到指定 commit假设为 abc123 git checkout abc123 -- data/news.jsonl git commit -m revert: rollback to news state at abc123 # 重新生成 Hugo 站点 hugo --minify整个过程不到 30 秒且所有中间状态均可追溯。5.5 进阶用 GitHub Actions 实现全自动每日抓取与部署在.github/workflows/daily-fetch.yml中name: Daily News Fetch Deploy on: schedule: - cron: 0 3 * * * # 每天 UTC 3 点北京时间 11 点执行 workflow_dispatch: jobs: fetch-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: token: ${{ secrets.PERSONAL_TOKEN }} # 用于提交 persist-credentials: false - name: Set up Python uses: actions/setup-pythonv4 with: python-version: 3.11 - name: Install dependencies run: | pip install requests beautifulsoup4 fake-useragent - name: Run fetch script run: python fetch_news.py - name: Convert JSONL to Hugo data run: python jsonl_to_hugo_data.py - name: Commit changes run: | git config --local user.email actiongithub.com git config --local user.name GitHub Action chmod x git_commit_after_fetch.sh ./git_commit_after_fetch.sh - name: Build and deploy uses: peaceiris/actions-hugov2 with: hugo-version: latest # Hugo 构建后自动推送到 gh-pages 分支注意PERSONAL_TOKEN需在仓库 Settings → Secrets 中配置权限至少包含contents: write。这套机制让「个人新闻中枢」真正变成一个活的系统你设定好信源和规则剩下的交给 Git 和 CI每天醒来就能看到结构清晰、可验证、可回溯的新鲜信息切片。我坚持用这个模板三年最大的体会是信息过载不是因为新闻太多而是因为没有建立属于自己的过滤、存档、回溯闭环。每次手动点开十几个网站查更新的疲惫感被每天早上一杯咖啡时间里自动刷新的静态页面取代——那不是偷懒是把认知带宽省下来去做真正需要人脑判断的事。希望帮到你。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号