fix: switch kuaishou route from HTML scraping to GraphQL API#141
fix: switch kuaishou route from HTML scraping to GraphQL API#141RyoSXu wants to merge 2 commits into
Conversation
The kuaishou route was relying on scraping the __APOLLO_STATE__ data embedded in the HTML homepage. Kuaishou has changed their page structure and the visionHotRank data is no longer present in the initial HTML, causing the route to fail with '快手页面结构变更' errors. This replaces the HTML scraping approach with a direct GraphQL API request to https://www.kuaishou.com/graphql using the visionHotRank query, which still returns the hot ranking data reliably. Changes: - Replace get() HTML request with post() GraphQL request - Remove APOLLO_STATE parsing logic (~50 lines) - Simplify KuaishouHotItem interface for GraphQL response shape - Add fallback search URL when photoId is unavailable Fixes imsyy#127
There was a problem hiding this comment.
Code Review
This pull request refactors the Kuaishou route to fetch hot ranking data directly via a GraphQL POST request instead of scraping the HTML page and parsing the Apollo state. This significantly simplifies the data retrieval logic and types. The review feedback highlights two important improvements: throwing an error if the GraphQL response structure is missing or malformed to prevent silent failures, and wrapping decodeURIComponent in a try-catch block to prevent potential URIError crashes from malformed external URLs.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| id: hotItem.id, | ||
| title: hotItem.name, | ||
|
|
||
| const items = result.data?.data?.visionHotRank?.items || []; |
There was a problem hiding this comment.
If the GraphQL API response structure changes or the request fails, result.data?.data?.visionHotRank?.items will be undefined, and items will default to an empty array []. This causes the route to silently return an empty list (with a 200 OK status) instead of throwing an error, making it difficult to detect and monitor failures.
We should throw an error if the expected data structure is missing, similar to how the previous implementation handled structural changes.
const items = result.data?.data?.visionHotRank?.items;
if (!items) {
throw new Error("快手接口返回数据格式异常,未找到 visionHotRank.items");
}| const items = result.data?.data?.visionHotRank?.items || []; | ||
| const listData: ListItem[] = items.map((item: KuaishouHotItem, index: number) => { | ||
| const photoId = item.photoIds?.[0]; | ||
| const poster = item.poster ? decodeURIComponent(item.poster) : undefined; |
There was a problem hiding this comment.
Calling decodeURIComponent directly on external data (item.poster) without error handling is risky. If Kuaishou returns a malformed URL containing an invalid percent-encoded sequence (e.g., a single % not followed by two hex digits), decodeURIComponent will throw a URIError and crash the entire request.
It is safer to wrap this in a try-catch block or use a safe decoding helper to ensure the route remains resilient.
let poster: string | undefined;
if (item.poster) {
try {
poster = decodeURIComponent(item.poster);
} catch {
poster = item.poster;
}
}Address Gemini Code Assist review feedback on PR imsyy#141: 1. Throw an error when visionHotRank.items is missing from the GraphQL response instead of silently returning an empty list, making failures easier to detect and monitor. 2. Wrap decodeURIComponent in a try-catch block to prevent URIError crashes when Kuaishou returns a poster URL with invalid percent-encoded sequences. Falls back to the raw URL on decode failure.
Summary
The kuaishou route was relying on scraping the
__APOLLO_STATE__data embedded in the HTML homepage. Kuaishou has changed their page structure and thevisionHotRankdata is no longer present in the initial HTML, causing the route to fail with快手页面结构变更errors.This PR replaces the HTML scraping approach with a direct GraphQL API request to
https://www.kuaishou.com/graphqlusing thevisionHotRankquery, which still returns the hot ranking data reliably.Changes
get()HTML request withpost()GraphQL requestKuaishouHotIteminterface for GraphQL response shapephotoIdis unavailableTesting
tsc --noEmit)Fixes #127