尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python爬取搜狗微信搜索:公众号数据采集与反爬实战指南
简介面向微信公众号数据采集入门者与爬虫开发者这套资源围绕搜狗微信接口实现公众号基础信息与历史文章抓取覆盖接口调用、参数处理、返回解析与异常规避等关键环节可帮助读者快速搭建一个轻量级采集原型。包内共三个文件包含两个以Python编写的脚本与一份Markdown说明文档脚本分别承担公众号信息查询与文章列表抓取功能文档对运行环境、请求头设置、翻页逻辑及常见问题做了简要说明整体压缩包仅2KB结构精简适合直接阅读和二次修改。目前已有1719人学习下载。借助这套脚本读者能直观理解搜狗微信搜索的数据交互方式掌握从链接构造到结果抽取的完整思路并据此扩展自定义字段、增量抓取或数据清洗等实用功能减少从零摸索的时间适合作为爬虫入门练习或内部工具的基础版本。1. 从搜狗微信搜索说起接口能拿到什么值得怎么用搜狗微信搜索weixin.sogou.com可能是目前唯一一个不需要你有一堆公众号后台权限就能“按公众号名称搜到账号信息按关键词搜到文章列表”的公开入口。很多做公众号数据分析、竞品监控、内容归档的人都会在这一层去抓公开数据公众号的微信号、认证主体、最近文章以及每篇文章的标题、链接、发布时间、阅读数部分可见。它不是官方开放平台没有稳定的授权流程但好在它不需要开发者资质也没有调用次数配额——只要你的请求行为足够克制就能稳定拿数据。这篇文章面向两类人一类是做内容运营想定期把同行公众号的新文章抓下来做选题分析另一类是搞知识库沉淀想把关注列表里的公众号文章自动存到本地。我会按“请求流程 → 信息抓取 → 文章正文提取 → 避坑 → 进阶”的顺序把搜狗微信接口这条链路完整拆开。这里不依赖任何第三方封装库直接用 requests 就能跑通代码里的参数和坑都是能照抄的。2. 搜狗微信的搜索机制不是正式接口但要按接口的规矩来2.1 搜狗微信搜索的页面结构与请求流程搜狗微信的搜索入口分为两类按公众号搜索和按文章搜索。公众号搜索的 URL 通常是这种格式https://weixin.sogou.com/weixin?type1query关键词ieutf8s_frominput_sug_n_sug_type_type1 表示搜公众号type2 表示搜文章。query 是关键词其他的一堆下划线参数是搜狗自己生成的客户端标识少传两个通常不影响结果但传了能降低被拦的概率。整个请求流程是先用一个普通浏览器 User-Agent 打开这个地址搜狗会返回一个 HTML 页面里面嵌着搜索结果列表每个结果包含公众号名称、微信号、认证信息、最近更新的一篇文章标题和时间。你需要的“公众号信息”其实就藏在这份 HTML 里不需要再调其他二次接口。比较麻烦的是搜狗在搜索结果页做了两件事一是给返回的 HTML 里部分字段加了加密和转义二是对高频请求会返回一个验证码页面。这两个坑后面第 5 章会详细讲这里先记住一件事搜狗的这个“接口”表面是网页本质上是一个动态参数较少、但反爬检查较多的 HTTP 接口。所以你在写代码时要按接口的思路去处理控制请求头、控制 Cookie、控制频率。2.2 为什么搜狗会成为事实上的公众号数据入口微信官方对公众号信息的获取限制得很严。公众号后台可以导出 CSV但只能拿到自己号的数据开放平台接口需要应用审核而且要用户授权。也就是说如果你没有号主的配合想去查任意一个公众号的认证主体、简介、最近文章正规开放接口是拿不到的。搜狗微信搜索做了个折中它跟微信有内容合作有权抓取公众号的公开信息并在自己的搜索页面展示。对普通从业者来说这就是一个不对个人开放、但对爬虫“半开放”的数据入口。你不需要登录搜狗账号也不需要接任何 SDK只要会模拟浏览器行为就能拿到数据。这也是为什么市面上大量公众号数据工具都基于搜狗微信搜索来做因为它是门槛最低、不需要企业资质的一条路。但要注意搜狗毕竟是搜索公司不是专门给爬虫提供 API 的。它做了很多“墙体”来防爬比如验证码、Cookie 校验、请求频率限制、结果页链接动态加密。这些都会在后续代码里一并处理。2.3 黑匣子一样的 Cookie 与 SNUID 机制第一次请求搜狗微信时服务器会下发两个关键 CookieSNUID 和 SUID。这两个值会在后续请求中作为身份标识。SNUID 尤其重要它是由访问时间、IP 和随机数生成的搜狗会用它来判断你是不是同一个客户端在连续请求。我一般会建议这样处理第一次请求不管返回什么先把 HTTP 响应里的 Set-Cookie 全部存下来之后每次都带上。注意别自己伪造 SNUID因为它跟 IP 有关联你伪造一个别人的容易被判定为异常。用 requests.Session 会自动管理这些但有一个细节要手动配置会话中要固定 User-Agent 和 Accept-Language不然搜狗会认为你不是同一个浏览器在访问。如果你第 1 次请求就遇到了验证码先别急着调代码把浏览器手动打开一次 weixin.sogou.com完成一次搜索然后再把浏览器里的 Cookie 复制出来放到自己代码的 headers 里。这是最快且最稳的过法比硬调参数靠谱得多。3. 用 requests 获取公众号信息列表最小可跑通的代码3.1 最基本的搜索请求带上必要参数和 UA下面这段代码是获取公众号信息最核心的请求。它不处理翻页只负责拿到第一页搜索结果import requests from urllib.parse import quote 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-Language: zh-CN,zh;q0.9, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/webp,*/*;q0.8, Referer: https://weixin.sogou.com/, } session requests.Session() session.headers.update(headers) keyword 科技美学 url https://weixin.sogou.com/weixin?type1query{}ieutf8.format(quote(keyword)) resp session.get(url, timeout10) print(resp.status_code) print(resp.text[:500])这段代码的逻辑很直接构建一个带 UA 和 Referer 的请求头用 Session 保持 Cookie然后请求 type1 的公众号搜索页。这里 quote(keyword) 是为了把中文关键词做 URL 编码不然搜狗直接返回 400。打印出来的 resp.text 如果包含“搜狗安全验证”说明被验证码卡住了如果包含公众号名称就说明正常返回了结果页。参数说明type1 是公众号搜索type2 是文章搜索这个参数不能错。ieutf8 是搜狗要求固定带的不传也能返回结果但传了更稳。timeout 建议 10 秒以上搜狗响应有时候会慢5 秒容易误报超时。Referer 第一次请求可以先不带但遇到部分异常响应时补上会有帮助。3.2 解析 HTML 里的公众号信息字段搜狗回复的 HTML 结构比较固定每个公众号搜索结果都在 class 为 wx-box 的 div 里。下面是提取关键字段的代码from bs4 import BeautifulSoup import re def parse_weixin_account_list(html): soup BeautifulSoup(html, html.parser) results [] for item in soup.select(.wx-box): # 公众号名称 name_tag item.select_one(.wx-name) name name_tag.get_text(stripTrue) if name_tag else # 微信号 account_tag item.select_one(.info span:last-child) account account_tag.get_text(stripTrue) if account_tag else # 清理掉 微信号 前缀 account re.sub(r^微信号, , account) # 认证主体 / 简介 desc_tag item.select_one(.txt-info) desc desc_tag.get_text( , stripTrue) if desc_tag else # 最近文章标题 article_tag item.select_one(.s-p a) article_url article_tag.get(href) if article_tag else article_title article_tag.get_text(stripTrue) if article_tag else results.append({ name: name, account: account, desc: desc, latest_article_title: article_title, latest_article_url: article_url, }) return results # 使用 data parse_weixin_account_list(resp.text) for d in data: print(d[name], d[account], d[desc][:50])解析逻辑分四步先定位所有 wx-box 节点再分别提取名称、微信号、简介和最近文章。这里有两个易踩的坑一是微信号在 html 里可能被拆成了多个 span要用 “:last-child” 拿到完整内容二是搜狗返回的 html 中部分字段可能有实体转义比如把 写成 BeautifulSoup 会自动反转但如果你用正则去匹配就要注意这些转义。参数说明select(.wx-box) 用的是 CSS 选择器速度比逐层 find 快。.info span:last-child 表示取 info 类节点下的最后一个 span通常这一项就是微信号。这里没有把头像和二维码链接加进来如果需要头像可以额外取 .wx-avatar img 的 src 属性但那是一个相对路径需要拼接上 https://weixin.sogou.com 前缀。3.3 翻页与参数边界搜狗公众号搜索结果默认只显示前 10 页每页最多 10 条。翻页参数是 pageURL 里加 page2 就是第二页。翻页逻辑就是把上面的 URL 循环 10 次每次改 page 值。但这里有个现实边界公众号搜索翻到第 3 页之后很容易触发验证码。这不是代码问题是搜狗的反爬策略它在用户角度也是这么限制的。所以我一般不建议把公众号搜索翻页太深。如果目标是把某个行业所有公众号都抓下来更稳的方式是用行业关键词做多词搜索每个词只抓前 2 页最后做去重合并。因为不同关键词会召回同一批公众号合并后覆盖率不一定比深翻第 8 页低但触发验证码的概率会小很多。这是个很实用的策略属于用搜索词的数量换取翻页深度。翻页请求改成这样for page in range(1, 3): # 只翻前两页 page_url url page{}.format(page) resp session.get(page_url, timeout10) time.sleep(3) # 每页之间至少间隔 3 秒 if 搜狗安全验证 in resp.text: print(第 {} 页触发验证码停止翻页.format(page)) break data parse_weixin_account_list(resp.text)这段代码加了 sleep(3) 来控制频率同时用验证码关键词做一个提前中断。如果你用这段代码跑发现前两页都能正常返回那说明当前的 IP 和 Cookie 状态是健康的如果第一页就触发验证码优先去换浏览器 Cookie而不是加大 sleep 时间。4. 从公众号到文章列表抓取文章信息和正文的关键步骤4.1 搜狗文章搜索与公众号文章页的两种路由搜狗微信里找公众号文章有两条路一条是通过公众号搜索结果里的“最近文章”链接直接进到文章页另一条是通过 type2 的文章搜索按关键词搜文章再从文章链接回到公众号。两条路的最终目标都是 article 详情页但文章搜索返回的是一个中间跳转页链接形如https://weixin.sogou.com/link?urlxxxxxx这个 link 地址点击后会经过一次 302 跳转最终落到 mp.weixin.qq.com 的正文页。你直接用 requests 去 get 这个 link 地址会把跳转后的最终 URL 拿到一般用 allow_redirectsTrue 就能自动跟过去。公众号搜索结果里的“最近文章”同样也是一个 link 跳转地址。所以后续代码里你只需要写一个函数接收任意 link 链接返回最终的文章页 HTML 和最终 URL。这样可以统一处理两种来源。4.2 提取文章列表参数与返回结构搜狗文章搜索的典型 URL 是https://weixin.sogou.com/weixin?type2query人工智能ieutf8返回的每一篇文章都在 li 标签里结构里有标题、公众号名称、发布时间、摘要。提取代码def parse_article_list(html): soup BeautifulSoup(html, html.parser) articles [] for li in soup.select(ul.news-list li): title_tag li.select_one(h3 a) if not title_tag: continue title title_tag.get_text(stripTrue) link title_tag.get(href) account_tag li.select_one(.account) account_name account_tag.get_text(stripTrue) if account_tag else time_tag li.select_one(.s2) publish_time time_tag.get_text(stripTrue) if time_tag else # 摘要通常在 .txt-info 里但有时会被截断 summary_tag li.select_one(.txt-info) summary summary_tag.get_text( , stripTrue) if summary_tag else articles.append({ title: title, link: link, account: account_name, publish_time: publish_time, summary: summary, }) return articles这里的重点在于文章标题在 h3 里的 a 标签公众号名在 .account 类里发布时间在 .s2 类里。搜狗对发布时间有三种格式xx分钟前、xx小时前、具体日期。如果你要做时间排序需要把这些格式统一转换只保留“昨天”“前天”这种会丢掉准确日期的字段所以我建议直接在摘要里找日期或者在点进文章正文之后再取发布时间。参数说明链接 link 不是完整 URL而是 /link?url 开头的相对路径。要拼上 https://weixin.sogou.com 前缀再访问。另外 .s2 字段查出来可能包含“2017年03月20日”这类格式要把“年”“月”去掉后转成标准时间才能进数据库。4.3 文章正文提取用正文页的元信息而非 pyquery 硬啃搜狗跳转后的文章正文页是 mp.weixin.qq.com 的页面。这个页面里正文内容在 id 为 js_content 的 div 里标题在 h1 或 meta 里作者在 id 为 js_name 的 span 里。提取代码def parse_article_content(final_resp): soup BeautifulSoup(final_resp.text, html.parser) # 标题先从 og:title 拿拿不到再用 h1 title_meta soup.find(meta, attrs{property: og:title}) title title_meta.get(content, ).strip() if title_meta else if not title: h1 soup.select_one(h1) title h1.get_text(stripTrue) if h1 else # 公众号名 account_meta soup.find(meta, attrs{property: og:article:author}) account account_meta.get(content, ).strip() if account_meta else # 正文js_content div content_div soup.select_one(#js_content) content_text content_div.get_text(\n, stripTrue) if content_div else return { title: title, account: account, content_text: content_text, final_url: final_resp.url, }正文提取看起来简单但有两个常见翻车点第一部分公众号开启了“图文素材保护”正文会被拆进多个 div.wx-temp 或做了懒加载直接取 js_content 可能只有开头一段第二正文里的图片在 HTML 里是>import sqlite3 from datetime import datetime conn sqlite3.connect(weixin_articles.db) conn.execute(CREATE TABLE IF NOT EXISTS articles ( title TEXT PRIMARY KEY, account TEXT, publish_time TEXT, final_url TEXT, content TEXT, created_at TEXT )) def save_article(article): cur conn.execute(SELECT 1 FROM articles WHERE title?, (article[title],)) if cur.fetchone(): return False # 已存在跳过 conn.execute( INSERT INTO articles (title, account, publish_time, final_url, content, created_at) VALUES (?,?,?,?,?,?), (article[title], article[account], article[publish_time], article[final_url], article[content_text], datetime.now().isoformat()) ) conn.commit() return True这里用 title 做主键去重。虽然理论上不同文章可能重名但这样最简单后面如果发现误删可以再把 (account, publish_time) 也纳入判断。存储正文用 TEXT 字段就够了不需要上 PostgreSQL单机爬 1 万篇文章也就几百 MB。6.2 把文章转成知识库格式从 HTML 到 Markdown正文存纯文本之后搜索是能搜了但对知识库来说没有标题层级和图片标记阅读体验会差很多。我通常会加一步把提取出来的 js_content HTML 直接转成 Markdown。这个转换可以用 html2text 库也可以自己用 BeautifulSoup 按标签转。核心是把 p 转成空行分隔把 h2/h3 转成 ## / ###把 img 转成。def html_to_markdown(content_html): soup BeautifulSoup(content_html, html.parser) lines [] for block in soup.find_all([p, h2, h3, img, section]): if block.name h2: lines.append(\n## block.get_text(stripTrue)) elif block.name h3: lines.append(\n### block.get_text(stripTrue)) elif block.name img: src block.get(data-src) or block.get(src, ) alt block.get(alt, ) lines.append(f![{alt}]({src})) else: text block.get_text( , stripTrue) if text: lines.append(\n text) return \n.join(lines)这里的要点有两个第一所有 img 标签的 src 属性值优先取 style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />
RELATED

相关推荐

副队长JavaScript教程(49)-主动抛出异常与错误类型

副队长JavaScript教程(49)-主动抛出异常与错误类型

点此查看 所有教程、项目、源码导航 文章目录1. 背景2. throw 抛出异常2.1 throw 的作用2.2 基础示例2.3 什么时候需要 throw3. JS 内置错误类型3.1 Error3.2 ReferenceError 引用错误3.3 TypeError 类型错误3.4 RangeError 范围错误4. 异常处理常见坑4.1 不要无脑捕获所有异常…

📅 2026/10/27 18:17:33
副队长JavaScript教程(48)-异常处理基础

副队长JavaScript教程(48)-异常处理基础

点此查看 所有教程、项目、源码导航 文章目录1. 背景2. 异常是什么3. try catch finally 基础语法3.1 try3.2 catch3.3 finally4. 错误对象 err 的常用属性5. 典型实战场景:调用不存在的函数6. 重要注意点7. 小结1. 背景 前面我们写的 JS 代码,都是预期…

📅 2026/10/27 18:17:33
TFLite Micro Introduce

TFLite Micro Introduce

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/27 18:17:33
MORE NEWS

更多资讯

📰

AI Agent 智能体实战:任务拆解、工具调用与结果校验闭环

做后端和数据处理的朋友最近大概率都遇到过这样的场景:手里有个 AI 对话工具,问它几个问题觉得挺顺手,于是想让它帮忙把一批文档整理成一份汇总报告,结果任务丢进去,返回的要么是泛泛而谈的套话,要么是看似…

📰

WinDbg(x86)蓝屏日志分析实战:从符号配置到驱动定位

简介:WinDbg(x86)是微软官方调试工具集中面向32位Windows系统的版本,主要服务于需要分析蓝屏内存转储文件、排查驱动与应用程序崩溃的开发者及系统管理员。资源围绕蓝屏日志查看这一核心场景,提供从加载dump文件到解读错误代码、停止消息及崩…

📰

GaussDB 5.0轻量级安装包Linux部署指南:从环境核对到参数调优

简介:面向Linux环境下希望快速部署华为GaussDB数据库的开发者与运维人员,这份资源提供openGauss-Lite 5.0.0轻量级安装包,适合资源有限但需要完整数据库特性的小型环境与测试场景。压缩包共13个文件、约22.14MB,以6个sh脚本为主&a…

📰

本地AI项目从0到1部署跑通:环境自检、接口验证与批量任务实操清单

拿到一个新的开源 AI 项目,很多人第一反应是先把仓库克隆下来,然后照着 README 一路pip install。结果往往卡在第三步:依赖装完了,模型没下全;模型下全了,显存不够;显存够了,端口又被…

📰

Mycat 1.6.7.1 CentOS 7 分库分表实战指南

简介:本资源为Mycat分布式数据库中间件在CentOS 7环境下的开箱即用部署包,面向Java后端开发、DBA及分布式系统架构学习者,解决MySQL单库性能瓶颈与水平扩展难题。压缩包包含95个文件,主体为42个核心jar包(含Mycat-serv…

📰

Linux网桥brctl实战:编译、STP调参与iproute2迁移

简介:围绕 Linux 桥接控制工具 brctl 的源码资源包,面向网络运维、系统管理与虚拟化实验学习者,用于理解并实践网桥创建、端口管理、STP 与 VLAN 等桥接配置能力。压缩包共 47 个文件、约 157KB,以 8 个 C 源文件和 3 个头文件为核…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬