You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批量请求Kijiji页面遇异常响应,疑遭反爬?求排查方案

批量请求Kijiji广告HTML时异常响应的排查方案

问题背景

开发程序通过批量GET请求从Kijiji获取约50个广告的HTML用于统计分析,遇到以下异常:

  • 前30-40次请求返回正常结果,后续请求返回异常HTML(浏览器打开为无限刷新的空页面)
  • 大量异常响应后会出现1-3次正常响应;将总请求数减至30时,15次正常请求后开始异常,末尾仍有1-3次正常响应
  • 手动分步执行(加断点)时所有请求均正常,仅循环自动执行时触发问题
  • 少量请求(5-10次)时程序运行正常,批量请求时出现异常

现有libcurl处理代码

extern size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream) {
    int written = fwrite(ptr, size, nmemb, (FILE*)stream);
    return written;
}

int txt_Upd(string myURL, int destination)
{
    CURL* curl_handle;
    static const char* headerfilename;
    CURLcode res;

    switch (destination){//create different files so we don't have to refresh the same one back and forth
    case 1: {
        headerfilename = "head.txt";
        break;
    }
    case 2: {
        headerfilename = "sr.txt";
        break;
    }
    case 3: {
        headerfilename = "aux1.txt";
        break;
    }
    }

    FILE* headerfile;
    curl_global_init(CURL_GLOBAL_ALL);

    curl_handle = curl_easy_init();

    curl_easy_setopt(curl_handle, CURLOPT_URL, myURL.c_str());
    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "VZM_Analytix");
    
    curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1L);
    curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "cookies.txt");
    //curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, "cookies.txt");

    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, TRUE);

    curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);

    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);

    headerfile = fopen(headerfilename, "w");
    if (headerfile == NULL) {
        curl_easy_cleanup(curl_handle);
        return 2;
    }
   
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, headerfile);
    res = curl_easy_perform(curl_handle);
    fclose(headerfile);
    curl_easy_cleanup(curl_handle);

    return res;
}

排查思路

1. 处理请求频率限制

Kijiji存在反爬机制,循环快速请求会触发限流,手动分步执行因间隔长未触发。可:

  • 在每次请求后添加1-3秒的随机延迟,模拟人类浏览间隔
  • 记录请求时间戳,确认异常出现时的请求间隔是否过短

2. 修复libcurl全局初始化问题

当前代码每次调用txt_Upd都执行curl_global_init(CURL_GLOBAL_ALL),该函数仅需在程序启动时调用一次,重复调用会导致资源泄漏或异常。将其移至程序入口处,不要放在请求函数内。

3. 启用Cookie持久化

当前仅设置CURLOPT_COOKIEFILE(读取Cookie),注释掉了CURLOPT_COOKIEJAR(保存Cookie)。Kijiji可能通过Cookie识别会话,未持久化Cookie会导致每次请求被当作新会话,易触发限制。取消注释CURLOPT_COOKIEJAR,确保Cookie在请求间持续有效。

4. 检查HTTP响应状态码

在curl_easy_perform后,调用curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &http_code)获取响应状态码,异常时可能返回429(请求过多)、503等状态,通过状态码确认是否被限流。

5. 模拟真实浏览器请求头

当前仅设置User-Agent,真实浏览器会发送更多请求头(如Accept、Accept-Language、Referer等)。添加这些头信息,让请求更接近正常浏览器:

struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
headers = curl_slist_append(headers, "Accept-Language: en-US,en;q=0.5");
headers = curl_slist_append(headers, "Referer: https://www.kijiji.ca/");
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
// 记得在curl_easy_cleanup前释放headers
curl_slist_free_all(headers);

6. 排查文件写入冲突

当前destination对应3个固定文件,若循环中重复使用同一destination,会导致文件内容混乱,看起来像异常响应。确保每次请求使用独立文件名,或确认destination参数在循环中分配正确。

7. 启用libcurl调试日志

添加CURLOPT_VERBOSE选项,输出详细请求和响应日志,查看异常请求的通信细节:

curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);

日志会显示请求头、响应头、连接状态等信息,帮助定位是请求被拦截还是响应异常。


内容的提问来源于stack exchange,提问作者Vroom ZOOM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:25:19