带有自定义标题的urllib.urlretrieve

rea*_*404 9 urllib python-3.x urlretrieve

我正在尝试使用urlretrieve,同时添加自定义标头来检索文件.

检查urllib.request我实现的代码源时,urlopen可以Request在参数中取一个对象,而不仅仅是一个字符串,允许放置我想要的头.但是如果我尝试做同样的事情urlretrieve,我会得到一个TypeError:期望的字符串或类似字节的对象,正如在这篇文章中提到的那样.

我最终做的是重写我自己的urlretrieve,删除抛出错误的行(该行与我的用例无关).

它工作正常,但我想知道是否有更好/更清洁的方式,而不是重写我自己的方式urlretrieve.如果可以传递一个自定义标题urlopen,感觉应该可以这样做urlretrieve吗?

Los*_*het 31

我找到了一种方法,你只需添加一些额外的代码行......

import urllib.request

opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
urllib.request.install_opener(opener)
urllib.request.urlretrieve("type URL here", "path/file_name")
Run Code Online (Sandbox Code Playgroud)

如果您想了解详细信息,可以参考python文档:https://docs.python.org/3/library/urllib.request.html


Qee*_*eek 5

urllib.request.urlretrieve()使用内部urllib.request.urlopen()(至少在Python 3)。因此,您可以使用相同的方式来影响的行为urlopen

urlopen(params)被调用时,它实际上首先查看特殊的全局变量urllib.request._opener,如果是,Noneurlopen使用默认的开启程序集来设置该变量,否则它将保留它。在下一步中,它将调用urllib.request._opener.open(<urlopen_params>)(在下一部分中,我urllib.request._opener仅称为opener)。

opener.open()包含处理程序不同协议的列表。当opener.open()被称为那么它会做的动作:

  1. 从URL urllib.request.Request对象创建(或者,如果您直接提供,Request它将使用它)。
  2. Request对象中提取协议(从URL方案推导得出)。
  3. 根据协议,它将尝试查找并使用以下方法:
    • protocol_request(例如http_request)-它用于在打开连接之前对请求进行预处理。
    • protocol_open -实际上与远程服务器建立连接
    • protocol_response -处理来自服务器的响应
    • 有关其他方法,请参阅Python的文档

对于您自己的开瓶器,您必须执行以下三个步骤:

  1. 创建自己的处理程序
  2. 处理程序的构建列表包含您的自定义处理程序(函数urllib.request.build_opener
  3. 将新的开瓶器安装到urllib.request._opener(功能urllib.request.install_opener)中

urllib.request.build_opener创建首战其中包含了除从哪个是你的自定义处理继承处理自定义处理程序,并添加默认叹为观止。

因此,要添加自定义标头,您可以编写如下内容:

import urllib.request as req

class MyHTTP(req.HTTPHandler):
    def http_request(self, req):
        req.headers["MyHeader"] = "Content of my header"
        return super().http_request(req)

opener = req.build_opener(MyHTTP())
req.install_opener(opener)
Run Code Online (Sandbox Code Playgroud)

从这一点开始,当您调用urllib.request.urlretrieve()或正在使用的任何东西时,urlopen()它将用于处理程序的HTTP通信。当您想返回默认处理程序时,可以调用:

import urllib.request as req   

req.install_opener(req.build_opener())
Run Code Online (Sandbox Code Playgroud)

老实说,我不知道这是不是比您更好/更干净的解决方案,但它在中使用了准备好的机制urllib