如何使用 python 取消缩短 URL?

Posted

技术标签:

【中文标题】如何使用 python 取消缩短 URL?【英文标题】:How can I un-shorten a URL using python? 【发布时间】:2011-11-01 10:59:57 【问题描述】:

我已经看过这个帖子了 - How can I unshorten a URL?

我对已解决答案的问题(即使用 unshort.me API)是我专注于缩短 youtube 链接。由于 unshort.me 很容易使用,因此几乎 90% 的结果都带有我无法解决的验证码。

到目前为止,我一直坚持使用:

def unshorten_url(url):
    resolvedURL = urllib2.urlopen(url)  
    print resolvedURL.url

    #t = Test()
    #c = pycurl.Curl()
    #c.setopt(c.URL, 'http://api.unshort.me/?r=%s&t=xml' % (url))
    #c.setopt(c.WRITEFUNCTION, t.body_callback)
    #c.perform()
    #c.close()
    #dom = xml.dom.minidom.parseString(t.contents)
    #resolvedURL = dom.getElementsByTagName("resolvedURL")[0].firstChild.nodeValue
    return resolvedURL.url

注意:cmets 中的所有内容都是我在使用返回验证码链接的 unshort.me 服务时尝试做的。

有没有人知道在不使用 open 的情况下完成此操作的更有效方法(因为它浪费带宽)?

【问题讨论】:

您在使用什么网址缩短器时遇到问题?你为什么要使用 unshort.me 呢?您的代码应该已经可以工作了,它应该按照重定向到真实 url 来缩短 url。 我不明白您所说的“不使用 open”是什么意思。短链接是进入别人数据库的钥匙;不查询数据库就无法展开链接。 当我阅读我引用的帖子 (***.com/questions/4201062/…) 时,它看起来像命令 urlopen GET 请求整个页面,所以当我要寻找的只是链接时,这是一种带宽浪费。建议的方法对我不起作用(unshort.me),所以我决定看看是否还有其他选择。 【参考方案1】:

一行函数,使用请求库,是的,它支持递归。

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

【讨论】:

我认为这个答案比投票最多的答案还要好。尝试使用来自 fb.net 的 url,它会返回正确的 url,而另一个什么也不做。 这是一个单行并且完美的工作。可能是最好的答案。 可能是一个奇怪的问题,但我应该在使用 request.head 后关闭连接吗? @TitoSanz 不,你可以检查代码,所有类型的请求都关闭会话(除非你自己打开会话):github.com/psf/requests/blob/…【参考方案2】:

在该问题中使用评分最高的答案(不是公认的答案):

# This is for Py2k.  For Py3k, use http.client and urllib.parse instead, and
# use // instead of / for the division
import httplib
import urlparse

def unshorten_url(url):
    parsed = urlparse.urlparse(url)
    h = httplib.HTTPConnection(parsed.netloc)
    resource = parsed.path
    if parsed.query != "":
        resource += "?" + parsed.query
    h.request('HEAD', resource )
    response = h.getresponse()
    if response.status/100 == 3 and response.getheader('Location'):
        return unshorten_url(response.getheader('Location')) # changed to process chains of short urls
    else:
        return url

【讨论】:

工作就像一个魅力 - 我昨天尝试了这个但无济于事,因为我收到了大约 70% 的退货错误。可能只是一次性的事情,这就是我驳回它的原因。感谢您的回复,并对我多余的问题感到抱歉。 作为后续,我只记得为什么这种方式对我不起作用。我正在开发一个 twitter 应用程序,在某些情况下 url 被缩短了两倍(这种情况发生了很多次)。例如,它将获取此视频 [u't.co/LszdhNP'] 并返回此 url etsy.me/r6JBGq - 我实际上需要此链接到的最终 youtube 地址。你知道有什么办法可以解决这个问题吗? 我的回答做了一个简单的改变 太好了,效果很好。我将对此进行更多研究,以便我更好地理解它,并在将来自己调整它。再次感谢。 一些网站(例如 twitter)会尝试强制从 http 重定向到 https。在这种情况下,您的解决方案将永远循环,因为所有连接都假定为 http 并将继续看到重定向标头。要验证这一点,请尝试运行 unshorten_url("http://t.co/t")。我建议检查 parsed.scheme 并可选择使用 httplib.HTTPSConnection()。【参考方案3】:

您必须打开它,否则您将不知道它将重定向到哪个 URL。正如格雷格所说:

短链接是进入别人数据库的钥匙;不查询数据库就无法展开链接

现在回答你的问题。

有没有人知道更有效的方法来完成这个操作 不使用open(因为浪费带宽)?

更有效的方法是不关闭连接,通过使用 HTTP 的 Connection: keep-alive 使其在后台保持打开状态。

经过一个小测试,unshorten.me 似乎将HEAD 方法考虑在内并重定向到自身:

> telnet unshorten.me 80
Trying 64.202.189.170...
Connected to unshorten.me.
Escape character is '^]'.
HEAD http://unshort.me/index.php?r=http%3A%2F%2Fbit.ly%2FcXEInp HTTP/1.1
Host: unshorten.me

HTTP/1.1 301 Moved Permanently
Date: Mon, 22 Aug 2011 20:42:46 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Location: http://resolves.me/index.php?r=http%3A%2F%2Fbit.ly%2FcXEInp
Cache-Control: private
Content-Length: 0

因此,如果您使用HEAD HTTP 方法,而不是GET实际上您最终会做两次相同的工作

相反,您应该保持连接处于活动状态,这只会为您节省一点带宽,但它肯定会节省的是每次建立新连接的延迟时间。建立 TCP/IP 连接昂贵

您应该避免与未缩短服务的保持活动连接数等于您自己的服务接收到的并发连接数。

您可以在池中管理这些连接。这是你能得到的最接近的。在tweaking your kernel 的 TCP/IP 堆栈旁边。

【讨论】:

非常感谢您提供的信息。我目前将使用上面的 Pedro Loureiro 答案,因为它目前正在工作。但是如果我遇到任何问题,我会参考这个。非常感谢。【参考方案4】:

这里的 src 代码几乎考虑了有用的极端情况:

设置自定义超时。 设置自定义用户代理。 检查我们是否必须使用 http 或 https 连接。 递归解析输入 url 并防止在循环中结束。

src代码在github上@https://github.com/amirkrifa/UnShortenUrl

欢迎 cmets ...

import logging
logging.basicConfig(level=logging.DEBUG)

TIMEOUT = 10
class UnShortenUrl:
    def process(self, url, previous_url=None):
        logging.info('Init url: %s'%url)
        import urlparse
        import httplib
        try:
            parsed = urlparse.urlparse(url)
            if parsed.scheme == 'https':
                h = httplib.HTTPSConnection(parsed.netloc, timeout=TIMEOUT)
            else:
                h = httplib.HTTPConnection(parsed.netloc, timeout=TIMEOUT)
            resource = parsed.path
            if parsed.query != "": 
                resource += "?" + parsed.query
            try:
                h.request('HEAD', 
                          resource, 
                          headers='User-Agent': 'curl/7.38.0'

                          )
                response = h.getresponse()
            except:
                import traceback
                traceback.print_exec()
                return url
            logging.info('Response status: %d'%response.status)
            if response.status/100 == 3 and response.getheader('Location'):
                red_url = response.getheader('Location')
                logging.info('Red, previous: %s, %s'%(red_url, previous_url))
                if red_url == previous_url:
                    return red_url
                return self.process(red_url, previous_url=url) 
            else:
                return url 
        except:
            import traceback
            traceback.print_exc()
            return None

【讨论】:

以上是关于如何使用 python 取消缩短 URL?的主要内容,如果未能解决你的问题,请参考以下文章

在 Google 表格中取消缩短网址

如何通过 TinyURL api 缩短包含“#”符号的 url?

如何使用httpclient c#调用bitly v4 api来缩短url?

AGC如何快速部署Serverless Url缩短模板

利用Python缩短URL链接

网址缩短网站如何工作?