Skip to main content
 首页 » 编程设计

python之通过带有有效用户代理的 urllib.request 的 urlopen 返回 405 错误

2025年05月04日14kerrycode

我的问题是关于python 3中的urllib模块,下面这段代码

import urllib.request 
import urllib.parse 
 
url = "https://google.com/search?q=stackoverflow" 
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'} 
 
try: 
    req = urllib.request.Request(url, headers=headers) 
    resp = urllib.request.urlopen(req) 
    file = open('googlesearch.txt.', 'w') 
    file.write(str(resp.read())) 
    file.close() 
 
except Exception as e: 
    print(str(e)) 

按我的预期工作,并将谷歌搜索“stackoverflow”的内容写入文件中。我们需要设置一个有效的 User-Agent,否则 google 不允许请求并返回 405 Invalid Method 错误。

我想到了下面这段代码

import urllib.request 
import urllib.parse 
 
url = "https://google.com/search" 
values = {'q': 'stackoverflow'} 
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'} 
 
data = urllib.parse.urlencode(values) 
data = data.encode('utf-8') 
 
try: 
    req = urllib.request.Request(url, data=data, headers=headers) 
    resp = urllib.request.urlopen(req) 
    file = open('googlesearch.txt.', 'w') 
    file.write(str(resp.read())) 
    file.close() 
 
except Exception as e: 
    print(str(e)) 

应该产生与第一个相同的输出,因为它是具有相同用户代理的相同谷歌搜索。但是,这段代码抛出异常并显示消息:“HTTP 错误 405:不允许使用方法”。

我的问题是:第二段代码有什么问题?为什么它不会产生与第一个相同的输出?

请您参考如下方法:

您收到 405 响应是因为您发送的是 POST 请求而不是 GET 请求。 Method not allowed 不应与您的用户代理 header 有任何关系。这是关于使用不正确的方法(get、post、put、head、options、patch、delete)发送 http 请求。

Urllib 发送一个 POST,因为您在 Request 构造函数中包含了 data 参数,如下所示:

https://docs.python.org/3/library/urllib.request.html#urllib.request.Request

method should be a string that indicates the HTTP request method that will be used (e.g. 'HEAD'). If provided, its value is stored in the method attribute and is used by get_method(). The default is 'GET' if data is None or 'POST' otherwise.

强烈建议使用 requests 库而不是 urllib,因为它有一个更明智的 api。

import requests 
response = requests.get('https://google.com/search', {'q': 'stackoverflow'}) 
response.raise_for_status()  # raise exception if status code is 4xx or 5xx 
with open('googlesearch.txt', 'w') as fp: 
    fp.write(response.text)  

https://github.com/requests/requests