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

如何获取给定关键词的Google真实搜索结果数量?

解决方案:规避reCAPTCHA并高效获取Google真实搜索结果数

我完全理解你的痛点——Google展示的虚假结果数和频繁的reCAPTCHA确实把批量查询搞得头大,尤其是你需要精确匹配的真实计数来排序主题重要性。下面从优化Selenium、规避检测、替代API三个方向给你可行的方案:

一、先优化脚本逻辑:大幅减少请求次数

你的原脚本逐页请求的方式太低效,而且容易触发检测。其实可以直接跳到接近真实结果数的页面,把请求从十几页压缩到2-3次,大幅降低被识别的概率。

修改后的核心逻辑示例:

def search_result_count(s):
    query = url_encode(s)
    # 获取首页初始虚假计数
    Firefox.get(BASE_SEARCH.format(query, 0))
    result_stats = Firefox.find_element(by='id', value='result-stats').text
    init_count = int([x.replace(',', '') for x in result_stats.split() if x.replace(',', '').isdigit()][0])
    
    # 直接跳转到大概率是最后一页的位置(根据你的案例,真实计数大多在200以内)
    guess_start = min(init_count, 200)
    Firefox.get(BASE_SEARCH.format(query, guess_start))
    
    current_stats = Firefox.find_element(by='id', value='result-stats').text
    current_count = int([x.replace(',', '') for x in current_stats.split() if x.replace(',', '').isdigit()][0])
    
    # 验证前一页是否还是初始虚假计数,确认真实值
    if current_count != init_count:
        prev_start = guess_start - 100
        Firefox.get(BASE_SEARCH.format(query, prev_start))
        prev_count = int([x.replace(',', '') for x in Firefox.find_element(by='id', value='result-stats').text.split() if x.replace(',', '').isdigit()][0])
        return current_count if prev_count == init_count else prev_count
    else:
        # 极少数情况真实计数超过200,再尝试更大的start值
        guess_start += 200
        Firefox.get(BASE_SEARCH.format(query, guess_start))
        return int([x.replace(',', '') for x in Firefox.find_element(by='id', value='result-stats').text.split() if x.replace(',', '').isdigit()][0])

二、彻底规避reCAPTCHA的Selenium配置

原生Selenium很容易被Google检测,推荐使用undetected-chromedriver替代,它专门针对Google的反爬机制做了指纹伪装,配合随机UA和延迟,基本可以避免验证。

步骤1:安装依赖

pip install undetected-chromedriver

步骤2:优化后的完整代码

import undetected_chromedriver as uc
from string import ascii_letters, digits
import random
import time

# 真实用户代理池,每次请求随机切换
USER_AGENTS = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
]

def url_encode(s):
    valid = digits + ascii_letters
    query = ''
    for c in s:
        if c in valid:
            query += c
        elif c == ' ':
            query += '+'
        else:
            query += ''.join(f'%{b:02X}' for b in c.encode('utf8'))
    return query

BASE_SEARCH = 'https://www.google.com.hk/search?q=%22{}%22&gl=us&hl=en&pws=0&start={}&num=100'

# 初始化伪装后的Chrome浏览器
options = uc.ChromeOptions()
options.headless = True
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument(f"user-agent={random.choice(USER_AGENTS)}")
driver = uc.Chrome(options=options)

def search_result_count(s):
    query = url_encode(s)
    # 首页请求,模拟人类延迟
    driver.get(BASE_SEARCH.format(query, 0))
    time.sleep(random.uniform(1.5, 3.0))
    
    # 鲁棒提取结果数(避免about位置变化的问题)
    result_stats = driver.find_element(by='id', value='result-stats').text
    init_count = int([x.replace(',', '') for x in result_stats.split() if x.replace(',', '').isdigit()][0])
    
    # 跳转到猜测的最后一页
    guess_start = min(init_count, 200)
    driver.get(BASE_SEARCH.format(query, guess_start))
    time.sleep(random.uniform(1.0, 2.5))
    
    current_stats = driver.find_element(by='id', value='result-stats').text
    current_count = int([x.replace(',', '') for x in current_stats.split() if x.replace(',', '').isdigit()][0])
    
    # 验证并返回真实计数
    if current_count != init_count:
        prev_start = guess_start - 100
        driver.get(BASE_SEARCH.format(query, prev_start))
        time.sleep(random.uniform(1.0, 2.5))
        prev_count = int([x.replace(',', '') for x in driver.find_element(by='id', value='result-stats').text.split() if x.replace(',', '').isdigit()][0])
        return current_count if prev_count == init_count else prev_count
    else:
        guess_start += 200
        driver.get(BASE_SEARCH.format(query, guess_start))
        time.sleep(random.uniform(1.0, 2.5))
        return int([x.replace(',', '') for x in driver.find_element(by='id', value='result-stats').text.split() if x.replace(',', '').isdigit()][0])

三、免费替代API方案(适合超大量查询)

如果需要批量查询上千个关键词,即使优化Selenium也可能触发频率限制,推荐使用Brave Search API:

  • 支持精确匹配(双引号语法和Google一致)
  • 返回的结果计数是真实值
  • 免费额度为每天1000次请求,完全满足你的需求

示例代码:

import requests

# 注册Brave Search API获取免费密钥
BRAVE_API_KEY = "你的API密钥"

def brave_search_count(s):
    encoded_query = url_encode(f'"{s}"')
    url = f"https://api.search.brave.com/res/v1/web/search?q={encoded_query}&count=1"
    headers = {"Accept": "application/json", "X-Subscription-Token": BRAVE_API_KEY}
    response = requests.get(url, headers=headers)
    data = response.json()
    return data.get("estimatedResults", 0)

注:Brave的结果数和Google略有差异,但对于主题重要性排序的相对值来说,完全可靠。

四、批量查询的额外注意事项

  • 随机请求间隔:设置5-10秒的随机延迟,避免触发频率限制
  • 缓存结果:对重复查询缓存结果,减少不必要的请求
  • IP轮换:如果请求量极大,可搭配免费代理池(或付费代理)进一步降低被限制的概率

内容的提问来源于stack exchange,提问作者Ξένη Γήινος

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:38:14