使用Python requests请求DuckDuckGo时的异常搜索问题
解决DuckDuckGo搜索含特殊字符查询返回无结果的问题
我之前也碰到过一模一样的情况——DuckDuckGo对自动化请求的检测相当严格,尤其是当查询里同时包含引号、星号这类特殊字符时,很容易被判定为非人类请求,直接返回空结果页面。下面是几个亲测有效的解决思路:
1. 模拟真实浏览器的完整请求头
requests库默认的请求头太"朴素"了,一眼就能被识别出是程序发起的请求。你需要补上浏览器会携带的关键头字段,比如User-Agent、Accept、Accept-Language,同时用会话保持Cookie,模拟真实用户的访问流程。
示例代码:
import requests from urllib.parse import quote query = '"*example"' encoded_query = quote(query) url = f"https://duckduckgo.com/html/?q={encoded_query}&kl=us-en" # 模拟Chrome浏览器的请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Referer": "https://duckduckgo.com/", "Connection": "keep-alive", "Upgrade-Insecure-Requests": "1" } # 先访问主页初始化会话并获取Cookie,再发起搜索请求 session = requests.Session() session.get("https://duckduckgo.com/", headers=headers) response = session.get(url, headers=headers) print(response.text)
2. 使用DuckDuckGo官方API(最推荐)
直接爬HTML页面本质上是"逆向"面向用户的界面,很容易触发反爬。而DuckDuckGo提供了专门的程序化搜索API,稳定性高,还能返回结构化的JSON数据,完全不需要担心反爬问题。
示例代码:
import requests from urllib.parse import quote query = '"*example"' url = f"https://api.duckduckgo.com/?q={quote(query)}&format=json&kl=us-en" response = requests.get(url) search_results = response.json() # 查看核心搜索结果 print("摘要内容:", search_results.get("Abstract", "无摘要")) print("相关主题:", [topic["Text"] for topic in search_results.get("RelatedTopics", [])])
这个API不需要复杂的请求头,返回的数据结构清晰,唯一的小缺点是结果数量可能比HTML页面少,但绝大多数场景下完全够用。
3. 确保URL编码的规范性
不要手动拼接URL中的查询字符串,一定要用标准的URL编码工具处理特殊字符。urllib.parse.quote()会自动处理双引号、星号这类字符,避免因为编码错误导致DuckDuckGo无法正确解析你的查询。
比如:
from urllib.parse import quote query = '"*example"' print(quote(query)) # 输出:%22%2Aexample%22
为什么浏览器能正常访问?
浏览器发起请求时会自动携带完整的请求头、会话Cookie,甚至会有一些浏览器特有的字段,DuckDuckGo会判定这是人类用户的正常操作;而Python requests默认的请求缺少这些关键信息,被反爬机制拦截后返回了伪装的"无结果"页面。
内容的提问来源于stack exchange,提问作者Jakob Greenfeld




