【问题标题】:Unshorten URL for Invalid / expired Hostnames?为无效/过期的主机名取消缩短 URL?
【发布时间】:2019-11-17 22:54:59
【问题描述】:

我使用以下代码 sn-p 使用 requests 库来缩短 URL。 sn-p 可以正确运行有效主机名的 URL 重定向和正在运行的网页。但是,当最终 URL 是无效网站时,此代码和不缩短 URL 的 sn-ps 的所有其他变体似乎都会失败。我仍然想得到最终的网页 url 是什么,不管它是无效的。 sn-p 是:

def unshorten_url(url):
    return requests.head(url, allow_redirects=True).url

print unshorten_url(<shortened URL>)

缩短的 URL 应重定向到此网页,该网页的主机无效。 http://trekingear.com/product/4-get-a-real-rocky-mountain-high/?utm_source=Content&utm_medium=Postings&utm_campaign=Guffey%20X%20Mass

但它返回给我这个错误:

requests.exceptions.ConnectionError: HTTPConnectionPool(host='trekingear.com', port=80): Max retries exceeded with url: /product/4-get-a-real-rocky-mountain-high/?utm_source=Content&utm_medium=Postings&utm_campaign=Guffey%20X%20Mass (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x10556dc50>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',))

这是我要缩短的 URL: 如何从此重定向链中提取此无效主机的最终 URL?

【问题讨论】:

    标签: python url python-requests


    【解决方案1】:

    你不应该像那样使用requests.head,因为默认情况下它会跟随 302 重定向多达 3 次。

    您可以禁用重定向(使用retries=False)并使用urlopen。然后返回的响应将始终将 302 内容作为其 url:

    urlopen(method, url, body=None, headers=None, retries=None,
    redirect=True, assert_same_host=True, timeout=<object object>,
    pool_timeout=None, release_conn=None, chunked=False, body_pos=None,
    **response_kw)
    

    从池中获取连接并执行 HTTP 请求。这是发出请求的最低级别调用,因此您需要指定所有原始详细信息。

    Parameters:   
    
        method – HTTP request method (such as GET, POST, PUT, etc.)
        body – Data to send in the request body (useful for creating POST requests, see HTTPConnectionPool.post_url for more convenience).
        headers – Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers.
        retries (Retry, False, or an int.) –
    
        Configure the number of retries to allow before raising a MaxRetryError exception.
    
        Pass None to retry until you receive a response. Pass a Retry object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry.
    

    这是相关的注释:

    如果False,则禁用重试并立即引发任何异常。此外,不会在重定向时引发MaxRetryError,而是会返回重定向响应。

    示例

    (我实际上在本地 Web 服务器上运行了一项不同的测试,但找不到提供 错误 302 请求的公共测试)。

    from urllib3 import PoolManager
    
    manager = PoolManager(10)
    
    req = manager.urlopen("GET", "http://en.wikipedia.org/wiki/Claude_E._Shannon", retries=False)
    
    print req.get_redirect_location()
    

    上面会从维基百科请求一个 HTTP 页面,从而生成到 HTTPS 的重定向:

    https://en.wikipedia.org/wiki/Claude_E._Shannon
    

    重定向不重试

    你的情况有点不同。您希望进行重定向,因为原始 URL 在第一次尝试时不会产生真正的重定向,但您希望获得失败的重定向。

    这里的问题是 重定向由与错误重试相同的代码处理,因此您不能只禁用后者。两者都不是,也不是两者兼有。

    然后您必须同时启用两者,并长期执行(拦截错误)。 您可能需要增加重试次数,这会在发生错误时减慢速度

    try:
        // Did not know you can't post a URL shortener in a SO answer. Live and learn.
        req = manager.urlopen("GET", "http(COLON)(SLASH)(SLASH)t(DOT)co(SLASH)eWWk8s8Hzj")
        loc = req.get_redirect_location()
    except MaxRetryError as fail:
        // build "loc" from scheme, host and url
        loc = "%s://%s%s" % (fail.pool.scheme, fail.pool.host, fail.url)
    
    print loc
    

    您的具体情况

    由于您使用的是 urllib3 包装器,因此您只需解开异常:

    try:
        # This is your existing code
        return requests.head(url, allow_redirects = True).url
    except requests.ConnectionError as fail:
        return "%s://%s%s" % (fail.args[0].pool.scheme, fail.args[0].pool.host, fail.args[0].url)
    

    不过,您应该提供其他可能的错误。

    【讨论】:

    • 我尝试将 allow_redirects 设置为 False,它不会引发错误,但也没有给我所需的最终 URL。如果主机无效,我想提取缩短器停止的最终 URL。将重定向设置为 False ,只能避免错误,这对我的情况没有帮助
    • 我可能误会了。我添加了一个测试示例。这是你要找的吗?如果出现错误的 302 重定向,这不会出错,它只会返回它希望您被重定向的位置。
    • 我已经更新了我的帖子,图片显示了我想要缩短的 URL。我试过你的sn-p,它只是返回原始的缩短的URL,而不是未缩短的。
    • 不,它没有。它返回相同的 url with https 协议,重定向到 http://dld.bz/dysBG,最终重定向到你想要的 URL。因此,您需要遵循重定向,直到出现错误。修改答案
    • 正如预期的那样,我已经以不同的方式处理了干净重定向的情况(不像上一个)。您的 sn-p 为失败的主机名工作。谢谢!
    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 2011-05-11
    • 2020-05-12
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    相关资源
    最近更新 更多