ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

京东评论API获取实战:从抓包到Python/VC++封装

京东评论API获取实战:从抓包到Python/VC++封装 如果你正想在项目里获取京东评论的API接口大概率已经发现在官方文档里翻半天根本找不到一个叫“获取商品评论”的现成接口。更头疼的是网上一搜“京东评论爬虫”出来的教程多半已经过期京东前端接口的名称和参数隔几个月就换一次照抄代码大概率直接扑街。这篇文章不是教你“破解”什么黑科技而是把我实际踩出来的路子整理一遍从浏览器抓包定位评论接口到用 Python 快速验证再到用 VC 访问 HTTP 服务端 API 接口并解析 JSON最后把那些 403、空数据、分页错乱之类的坑一起列出来。无论你是做数据分析、竞品监控还是想给内部工具补一个“商品口碑”模块这套方法论都能直接用学完还能横移到小说 API、股票数据接口这类 RESTful API 场景上。1. 京东评论API难拿的真相与三条可行路径1.1 为什么官方API里没有现成的获取评论接口很多人觉得京东这么大的开放平台肯定提供了“评论API接口”只是自己没找到。实话实话京东开放平台确实给商家和合作服务商提供了一些评价相关的接口但主要用于商家后台查看订单评价、回复评价不是给普通开发者“拿某个商品的公开评论列表”用的。这类接口通常要求你有商家账号、建应用、申请权限、拿到 access_token而且在审核阶段基本就卡掉了个人开发者。就算你通过了商家端 API 权限接口返回的数据也不是你想的那种“直接能展示的评论全文”更多是评价维度、评分统计之类。所以纯民间场景下大家嘴里说的“京东评论API”实际上指的是商品详情页里那个前端的 H5 异步接口。它不是公开文档里的正式服务但只要你模拟浏览器正常请求就能拿到结构化的 JSON 评论数据。这属于“页面接口抓包复用”本质上是爬虫但有别于绕过加密签名的高危操作它在技术门槛和数据量上都比较温和。1.2 三条可行路径的对比与选型建议先把我实际用过的方案摆出来按推荐程度从低到高排方案获取难度数据完整性合规风险适合场景官方开放平台 API高需商家资质审核较强但仅限授权范围低商家自营系统、正规合作服务方第三方聚合数据服务商低付费购买次数取决于服务商渠道中注意服务商数据来源快速上线、对数据时效要求不高的小工具自己抓包 H5 评论接口中需要会抓包和反风控完整包含评论正文、时间、评分、追评中高需要遵守平台规则和频率学习研究、内部监控、低频个人项目个人角度我一般推荐第三条路径但强烈建议把它定位成“学习研究”而不是“商业爬虫”。理由很简单接口是活的官方页面怎么改你的解析脚本就得怎么跟。把它当成一个可复用的“评论API接口封装”来做比每次手动复制数据省心得多也比依赖第三方服务商的“黑盒数据”更可控。2. 核心接口拆解抓包定位京东评论数据接口2.1 用浏览器开发者工具找到真实评论接口先把某件商品的详情页打开比如你在地址栏里能看到??sku100012043978之类这个sku就是商品ID后面所有请求都靠它。然后按 F12 打开开发者工具切到 Network 面板刷新页面后在商品评价Tab里随便翻一页。这时候面板里会出现大量请求别乱看直接聚焦在 XHR 请求上搜关键字comment或者getCommentListPage。我自己实测下来稳定能用的一个 H5 评论接口是https://sclub.jd.com/comment/page.service.CommentService/getCommentListPage.action它的核心参数就那么几个productId: 100012043978 page: 0 pageSize: 10 sortType: 5 score: 0 isShadowSku: 0 fold: 1注意这里第一页的page是 0不是 1。这个接口不加callback参数时返回纯 JSON加了callback会返回 JSONP 格式方便浏览器端绕跨域。抓包时你看到的可能是带callbackjQueryxxxxx的 URL去掉 callback 再请求一样能拿到数据而且解析更干净。抓包有个习惯要养成不要只复制 URL要把请求头里的User-Agent和Referer一起抄下来。评论接口对Referer不算苛刻但缺了它偶尔会返回 403。User-Agent直接用一个真实 Chrome 的值就行千万别用 Python 默认的python-requests。2.2 关键参数说明与分页逻辑这些参数我是反复试出来的说几个容易踩坑的地方sortType排序方式5 是按时间排序6 是按推荐排序0 貌似是默认综合。想抓最新评论就用 5想抓热评就用 6。score评分筛选0 是全部1 是一星2 是二星3 是三星4 是四星5 是五星。要分析差评直接让 score1。isShadowSku这个参数挺关键。有些商品会有“关联SKU”的评论聚合比如多规格商品的一些评论挂在旧SKU下。填 0 表示只拿当前SKU的评论填 1 会把隐藏款式的评论也带出来但返回结构会变。我建议先用 0。fold折行参数1 表示不折叠用来拿更多追评内容。接口返回的 JSON 里顶层是一个comments数组数组里每个元素包含content评论内容、creationTime评论时间、score评分、nickname脱敏昵称、productColor、productSize等字段。还可能有一个maxPage字段用来判断总共有多少页。真要翻全量评论就while page maxPage一页一页拉但实际跑下来建议加个次数上限别一次性刷几千页否则很容易被风控。3. 从快速验证到工程封装Python 与 VC 两种实战打法3.1 先用 Python 五分钟验证评论接口不管你最终打算用 Python 还是 VC我强烈建议先用 Python 把接口跑通验证参数、字段、分页逻辑都没问题之后再移植到别的语言。原因很简单Python 写起来快调试成本低接口长什么样、返回什么字段一眼就能看明白。下面这段代码是我常用的最小验证脚本import requests import time product_id 100012043978 url https://sclub.jd.com/comment/page.service.CommentService/getCommentListPage.action session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36, Referer: fhttps://item.jd.com/{product_id}.html, Accept: application/json, text/plain, */*, Accept-Encoding: gzip, deflate, br, }) params { productId: product_id, page: 0, pageSize: 10, sortType: 5, score: 0, isShadowSku: 0, fold: 1, } resp session.get(url, paramsparams, timeout10) data resp.json() for comment in data[comments]: print(comment[creationTime], comment[score], comment[content])跑通之后你就可以在这个基础上做二次封装比如包装成一个fetch_jd_review(product_id, page, page_size)函数再丢给后续的数据清洗模块。需要注意一点接口返回的是 gzip 压缩内容但requests会自动解压不需要手动处理。如果你用的是 VC就得自己考虑解压这一步了。3.2 用 VC/WinHTTP 调用 RESTful API 的封装样例有些场景必须用 VC比如你的产品本身是 Windows 桌面客户端不想为了一个评论接口再内嵌一个 Python 解释器又或者你要把这个接口封装成底层库给现有 C 业务模块调用。这时候用 WinHTTP 是最直接的办法它是 Windows 系统自带的 HTTP 栈不需要引入第三方重量级依赖。先看核心的 HTTP GET 封装我习惯写成一个长这样的函数#include windows.h #include winhttp.h #include string #include vector #include nlohmann/json.hpp #pragma comment(lib, winhttp.lib) std::string HttpGetJson(const std::wstring host, const std::wstring path, const std::wstring referer, const std::wstring cookie, DWORD timeoutMs) { HINTERNET hSession WinHttpOpen( LJDCommentClient/1.0, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); HINTERNET hConnect WinHttpConnect( hSession, host.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0); HINTERNET hRequest WinHttpOpenRequest( hConnect, LGET, path.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); WinHttpSetTimeouts(hRequest, timeoutMs, timeoutMs, timeoutMs, timeoutMs); if (!referer.empty()) { std::wstring refererHeader LReferer: referer; WinHttpAddRequestHeaders(hRequest, refererHeader.c_str(), (ULONG)-1L, WINHTTP_ADDREQ_FLAG_REPLACE); } if (!cookie.empty()) { std::wstring cookieHeader LCookie: cookie; WinHttpAddRequestHeaders(hRequest, cookieHeader.c_str(), (ULONG)-1L, WINHTTP_ADDREQ_FLAG_REPLACE); } BOOL sent WinHttpSendRequest( hRequest, WINHTTP_NO_EXTRA_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); if (!sent) { DWORD err GetLastError(); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); throw std::runtime_error(WinHttpSendRequest failed: std::to_string(err)); } WinHttpReceiveResponse(hRequest, NULL); std::vectorchar responseData; DWORD available 0; do { WinHttpQueryDataAvailable(hRequest, available); if (available 0) break; size_t oldSize responseData.size(); responseData.resize(oldSize available 1); DWORD bytesRead 0; if (!WinHttpReadData(hRequest, responseData[oldSize], available, bytesRead)) { break; } responseData.resize(oldSize bytesRead); } while (available 0); WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return std::string(responseData.begin(), responseData.end()); }调用的时候把 host、path、referer 拼好就行std::wstring host Lsclub.jd.com; std::wstring path L/comment/page.service.CommentService/ LgetCommentListPage.action? LproductId100012043978page0pageSize10 LsortType5score0isShadowSku0fold1; std::wstring referer Lhttps://item.jd.com/100012043978.html; std::wstring cookie L; // 如果页面需要cookie这里填抓包复制的值 std::string jsonText HttpGetJson(host, path, referer, cookie, 10000);这个封装的核心点在于 WinHTTP 的句柄管理WinHttpOpen管 SessionWinHttpConnect管连接WinHttpOpenRequest管请求用完必须逐个CloseHandle。别只关最后一个否则句柄泄漏。另外WinHttpSendRequest的网络超时默认可能很长一定要用WinHttpSetTimeouts设置否则接口卡住时界面直接假死。拿到jsonText之后原生 C 没有内置 JSON 解析我用的是nlohmann/json一个 header-only 库整个项目里加个头文件就能用auto data nlohmann::json::parse(jsonText); for (const auto item : data[comments]) { std::string content item.value(content, ); std::string time item.value(creationTime, ); int score item.value(score, 0); // 这里自己决定是打印、入库还是回调业务层 }如果你的项目不方便引入 nlohmann也可以用 Windows 自带的IXMLDOMDocument把 JSON 当 XML 解析但体验非常痛苦。相比之下nlohmann 几乎是现在 VC 世界里最省心的 JSON 方案。3.3 顺带说一句让豆包这类AI助手帮你写绑定代码最近不是特别流行让“豆包”这种 AI 助手帮忙写代码吗我在做 VC 封装时也试过先把上一节抓包得到的接口请求参数整理成一段自然语言描述再让豆包生成客户端调用代码效果相当可以。尤其是从零开始写 WinHTTP 封装时AI 能给你一个能跑的骨架你再花几分钟把超时、Header、错误处理补扎实效率比手敲快一倍。不过我得提醒一句AI 生成的代码里经常有想当然的参数名比如把sortType写成sort、把page当成从 1 开始。这种问题不会报错但会返回错误数据。所以任何 AI 生成的请求代码都要先用 Python 脚本跑一遍同样的参数确认返回值后再往 C 里搬。4. 实测过程中的高频坑与排查速查4.1 403 与风控我刚开始写这个接口的时候脸不红心不跳地用一个for循环直接从第 0 页刷到第 100 页结果刷到第 20 页左右请求开始返回 403。这是京东对非正常浏览行为的拦截最常见的原因有两个请求头的User-Agent太假或者Referer缺失。单 IP 短时间请求频率过高。解决办法也不复杂加延时是必须的我个人习惯在两次请求之间随机睡 1 到 3 秒不要用固定间隔固定间隔更容易被识别成机器。另外User-Agent一定不要让它保留python-requests这种默认值。如果 403 已经出现通常过几分钟会自动解封这时候停下来冷静一下别继续怼。提示千万别尝试绕过滑块验证或者通过异常手段伪造用户身份这条路不仅不稳定还会带来法律风险。合规处理比数据量重要得多。4.2 返回空数据另一个高频问题是接口正常返回 200但comments数组是空的。这种情况十有八九是参数没配对。我遇到过几种productId传错了从商品链接里复制的时候多带了小数点或者其他字符。page超出maxPage返回空是正常的。score填了 5而这个商品确实一个五星评价都没有接口一样会返回空数组。排查的时候先固定pageSize10、score0、sortType5用浏览器打开同一个商品的评价页做对照。如果浏览器有数据而请求没有那就是请求头少了Referer。还有一个细节有些商品的评价接口不是sclub.jd.com而是club.jd.com下的旧版路径两者返回结构略有差异。建议以浏览器抓包到的主机名为准不要只看网上抄来的代码。4.3 数据合规你必须有数聊了这么多技术细节我必须把这条放前面京东评论数据是用户生成内容受平台用户协议保护。未经授权大规模抓取并用于商业运营存在明确的法律风险即便只是学习研究也要严格控制频率不要给目标服务器造成压力。我的做法是单商品数据量控制在几百条以内跑完就停不搞全量备份更不会把数据打包卖出去。如果你是真的想做一个长期供货的评论数据服务我不建议自己爬而是去申请正规数据合作渠道。宁可花钱买稳定也别让自己陷入随时可能收到律师函的被动局面。4.4 高频问题对照表下面这个表是我从多个项目里整理出来的最适合贴在项目文档里当速查现象可能原因排查方法返回 403User-Agent 缺失、Referer 不对、访问过快检查请求头加上真实 UA增加随机延时返回 200 但 comments 为空productId 错、page 越界、score 筛选过严浏览器对照参数先固定全量筛选JSON 解析报错返回了 JSONP 而不是纯 JSON去掉 callback 参数或用文本替换处理中文字段乱码请求时没带 gzip 头或编码识别错保证 Accept-Encoding 正确用 UTF-8 解码VC 请求一直卡住没有设置 WinHttpSetTimeouts设置发送、接收超时建议 10 到 30 秒再分享一个我实际的排查小技巧写 VC 封装时最怕的不是接口请求本身而是接口返回数据被截断。WinHTTP 读取响应时必须循环调用WinHttpQueryDataAvailable和WinHttpReadData不能只读一次。我第一次写示例代码时就只读了一次结果总是只能拿到半个 JSON后面解析一直报错。所以上面那套循环读法建议原样保留别精简。5. 最后再补充一点我的个人心得如果你只是拿这个接口练手我建议你在 Python 版本跑通之后再费点时间把 VC 版本整理成一个带缓存、带超时重试的小类。因为京东评论接口的数据时效性很强今天写的脚本明天可能就少了几个参数把它封装成清晰的函数后续改起来会快很多。我在实际项目中就是靠这个方式把评论接口的维护周期从一个星期缩短到了半天。另外别把目光只锁在京东评论上。你现在会抓包定位接口、会构造请求参数、会用 Python 或 VC 解析 JSON这套能力放到小说 API、股票数据接口、天气接口、远程压缩服务接口上完全通用。说白了所谓“获取京东评论API接口”本质就是一次标准的 HTTP RESTful 接口对接找对 URL带对头解析好响应剩下的全是耐心。把这个思路吃透以后再遇到任何“某某平台接口怎么拿”的问题你都具备了自己动手解决问题的能力。
返回列表