news 2026/4/19 13:31:56

告别手动保存!用Python自动化下载雪球文章并生成带书签的PDF合集

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
告别手动保存!用Python自动化下载雪球文章并生成带书签的PDF合集

告别手动保存!用Python自动化下载雪球文章并生成带书签的PDF合集

每次在雪球上看到有价值的投资分析文章,你是不是也习惯性地点击收藏?但收藏夹里的内容越来越多,查找起来反而更麻烦。更糟的是,有些文章可能因为各种原因被删除或修改,手动保存的本地副本又杂乱无章。作为一名经常研究市场动态的技术爱好者,我花了三个月时间开发了一套自动化解决方案,现在分享给同样有这种痛点的你。

这套工具的核心价值在于:一键抓取指定作者的全部历史文章,自动生成结构清晰、带书签导航的PDF合集。不仅保留了原文的完整格式,还能按照发布时间、点赞数等维度进行智能排序。下面我就从环境准备到完整实现,详细拆解每个技术环节。

1. 环境准备与基础工具链

工欲善其事,必先利其器。我们需要搭建一个既能高效抓取网页内容,又能完美保留排版样式的处理流水线。以下是经过我实际验证的工具组合:

# 核心依赖清单 requirements = [ 'requests>=2.28.1', # 网络请求 'beautifulsoup4>=4.11.1', # HTML解析 'pdfkit>=1.0.0', # HTML转PDF 'pandas>=1.5.0', # 数据整理 'PyPDF2>=2.11.0', # PDF合并 ]

安装这些库只需一行命令:

pip install requests beautifulsoup4 pdfkit pandas PyPDF2

注意:pdfkit需要额外安装wkhtmltopdf引擎,Windows用户可从官网下载安装包,Mac用户建议使用brew install wkhtmltopdf

我对比过三种HTML转PDF方案,下面是性能测试数据:

方案渲染质量速度中文支持书签生成
pdfkit★★★★☆中速完美需手动
weasyprint★★★☆☆快速一般不支持
playwright★★★★★慢速完美自动

最终选择pdfkit是因为它在质量与效率之间取得了最佳平衡,虽然书签生成需要额外处理,但稳定性远超其他方案。

2. 雪球文章抓取实战

雪球的网页结构经过多次改版,但核心数据接口仍然保持稳定。通过分析XHR请求,我发现了一个隐藏的API接口:

def fetch_xueqiu_articles(user_id, max_page=10): """抓取指定用户的所有文章""" articles = [] base_url = f"https://xueqiu.com/u/{user_id}" for page in range(1, max_page + 1): params = { "page": page, "size": 20 # 每页数量 } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "X-Requested-With": "XMLHttpRequest" } try: response = requests.get(base_url, params=params, headers=headers) data = response.json() articles.extend(data['list']) except Exception as e: print(f"第{page}页抓取失败: {str(e)}") return articles

这个函数会返回包含以下字段的JSON数据:

  • title: 文章标题
  • description: 摘要内容
  • created_at: 发布时间戳
  • view_count: 阅读数
  • reward_count: 打赏数

提示:雪球对频繁请求有防护机制,建议在请求间添加time.sleep(random.uniform(1, 3))模拟人工操作

获取到文章列表后,我们需要用BeautifulSoup清洗HTML内容:

def clean_html(content): """净化雪球文章HTML""" soup = BeautifulSoup(content, 'html.parser') # 移除广告元素 for ad in soup.select('.ad-container, .recommend-article'): ad.decompose() # 修复图片链接 for img in soup.select('img'): if img.get('data-original'): img['src'] = img['data-original'] return str(soup)

3. 生成带书签的PDF

这是整个流程最关键的环节。普通的HTML转PDF会丢失文档结构,我们需要通过以下步骤实现智能书签:

def html_to_pdf_with_bookmark(html_path, pdf_path, title): """转换HTML为带书签的PDF""" options = { 'encoding': 'UTF-8', 'page-size': 'A4', 'margin-top': '15mm', 'margin-right': '15mm', 'margin-bottom': '15mm', 'margin-left': '15mm', 'quiet': '', 'title': title, } pdfkit.from_file(html_path, pdf_path, options=options) # 添加PDF书签 with open(pdf_path, 'rb') as f: reader = PdfReader(f) writer = PdfWriter() for page in reader.pages: writer.add_page(page) # 添加根书签 writer.add_outline_item(title, 0) with open(pdf_path, 'wb') as f_out: writer.write(f_out)

实际应用中,我会先批量生成单篇文章PDF,再用下面的方法合并:

def merge_pdfs(pdf_list, output_path, bookmarks): """合并PDF并保留书签结构""" merger = PdfMerger() for idx, pdf in enumerate(pdf_list): merger.append(pdf) if idx < len(bookmarks): merger.add_outline_item(bookmarks[idx], idx) merger.write(output_path) merger.close()

4. 高级功能扩展

基础功能实现后,我进一步优化了三个实用特性:

1. 智能排序系统

def sort_articles(articles, method='time'): """支持多种排序方式""" if method == 'time': return sorted(articles, key=lambda x: x['created_at']) elif method == 'popular': return sorted(articles, key=lambda x: -x['view_count']) elif method == 'comments': return sorted(articles, key=lambda x: -x['comment_count'])

2. 元数据导出

def export_metadata(articles, output_format='csv'): """导出文章统计数据""" df = pd.DataFrame(articles) if output_format == 'csv': df.to_csv('articles_meta.csv', index=False) elif output_format == 'excel': df.to_excel('articles_meta.xlsx', index=False)

3. 增量更新机制

def check_updates(user_id, last_crawl_time): """只抓取新发布的文章""" new_articles = [] current_page = 1 while True: batch = fetch_articles(user_id, page=current_page) if not batch: break new_in_batch = [a for a in batch if a['created_at'] > last_crawl_time] new_articles.extend(new_in_batch) if len(new_in_batch) < len(batch): break current_page += 1 return new_articles

5. 异常处理与性能优化

在实际运行中,我遇到了几个典型问题及解决方案:

常见故障排查表

现象可能原因解决方案
中文乱码编码声明缺失在HTML添加<meta charset>
图片加载失败防盗链机制修改请求头Referer字段
PDF生成超时复杂CSS渲染设置超时参数timeout=60
书签跳转偏移页码计算错误使用PyPDF2的add_outline_item

对于大规模抓取,建议采用以下优化策略:

  • 使用异步请求库(aiohttp)提升IO效率
  • 实现断点续传功能
  • 分布式任务队列(Celery+RabbitMQ)
# 异步抓取示例 async def async_fetch(url): async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.text()

经过三个月的迭代,这套系统已经稳定处理了超过5万篇雪球文章。最让我自豪的是为一个私募基金客户自动整理的行业研究报告库,包含327位分析师的1.2万篇文章,按行业、时间、热度等多维度分类,PDF总大小控制在800MB以内,书签层级深度达到4级。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 13:28:21

3分钟解锁:告别网盘限速的智能解析方案

3分钟解锁&#xff1a;告别网盘限速的智能解析方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅雷云盘…

作者头像 李华
网站建设 2026/4/19 13:21:57

终极离线Minecraft启动器指南:解锁你的游戏自由之旅

终极离线Minecraft启动器指南&#xff1a;解锁你的游戏自由之旅 【免费下载链接】Launcher Offline Minecraft launcher. 项目地址: https://gitcode.com/gh_mirrors/lau/Launcher 你是否厌倦了每次启动Minecraft都要登录官方账户&#xff1f;想要一个真正自由的游戏体验…

作者头像 李华
网站建设 2026/4/19 13:21:54

Unity Gameplay Ability System终极指南:5分钟构建专业级技能框架

Unity Gameplay Ability System终极指南&#xff1a;5分钟构建专业级技能框架 【免费下载链接】unity-gameplay-ability-system A unified framework for implementing ability systems in Unity 项目地址: https://gitcode.com/gh_mirrors/un/unity-gameplay-ability-system…

作者头像 李华