如何使用python取消缩短URL?

时间:2011-08-22 20:17:50

标签: python curl youtube hyperlink urllib

我已经看过这个帖子了 - 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

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

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

5 个答案:

答案 0 :(得分:15)

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

# 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

答案 1 :(得分:13)

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

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

答案 2 :(得分:2)

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

  

短链接是其他人数据库的关键;您无法在不查询数据库的情况下展开链接

现在回答你的问题。

  

有没有人知道更有效的方法来完成此操作   不使用开放(因为它浪费带宽)?

更有效的方法是不使用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堆栈旁边。

答案 3 :(得分:1)

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

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

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

欢迎评论......

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

答案 4 :(得分:0)

我可以在这里复制它,但是最好指向一个来自Dive Into Python的页面,所有这些都是关于handling redirects,这正是你想要在这里做的。