【问题标题】:How do I get a real file url in python 2.7?如何在 python 2.7 中获取真实的文件 url?
【发布时间】:2018-06-21 23:10:18
【问题描述】:

我有一个网址http://www.vbb.de/de/datei/GTFS_VBB_Nov2015_Dez2016.zip,它会将我“重定向”到http://images.vbb.de/assets/ftp/file/286316.zip。重定向引号,因为 python 说没有重定向:

    In [51]: response = requests.get('http://www.vbb.de/de/datei/GTFS_VBB_Nov2015_Dez2016.zip')
        ...: if response.history:
        ...:     print "Request was redirected"
        ...:     for resp in response.history:
        ...:         print resp.status_code, resp.url
        ...:     print "Final destination:"
        ...:     print response.status_code, response.url
        ...: else:
        ...:     print "Request was not redirected"
        ...:     
    Request was not redirected

状态码也是 200。response.history 什么也没给出。 response.url 给出第一个 url 而不是真实的。但是可以在 firefox -> developer tools -> network 中获取真正的 url。我如何在 python 2.7 中制作?提前致谢!!

【问题讨论】:

  • 我在该请求中看不到任何重定向。我得到一个200 响应代码(重定向将返回一个301302 响应代码和Location 标头)。
  • @larsks,是的,这甚至是问题所在。如果有重定向,我可以轻松获取 url。
  • 所以我想我不明白你的问题。 requests 只是一个 http 模块。它根本不解析内容。如果由于文档中的内容(meta 标签、javascript)而发生重定向,则您需要自己处理返回的内容。
  • 真正的问题是服务器返回什么以便 Firefox 获取它,以及如何在代码中做到这一点。您的问题没有包含足够的详细信息来帮助我们帮助您解决这个问题。也许一些勇敢的灵魂想要进行挖掘,但它确实应该从一开始就包含在您的问题中。
  • Dmitri,正如我所说,重定向是由于文档内容而发生的(在本例中,<head> 元素中的 meta http-equiv="refresh" 标记)。如果需要,您需要自己解析。

标签: python python-2.7 url redirect python-requests


【解决方案1】:

您需要先手动执行重定向,方法是从第一个返回的 HTML 中解析新的 window.location.href。然后,这会创建一个 301 回复,其中包含返回的 Location 标头中包含的目标文件的名称:

import requests
import re
import os

base_url = 'http://www.vbb.de'
response = requests.get(base_url + '/de/datei/GTFS_VBB_Nov2015_Dez2016.zip')
manual_redirect = base_url + re.findall('window.location.href\s+=\s+"(.*?)"', response.text)[0]
response = requests.get(manual_redirect, stream=True)
target_filename = response.history[0].headers['Location'].split('/')[-1]

print "Downloading: '{}'".format(target_filename)
with open(target_filename, 'wb') as f_zip:
    for chunk in response.iter_content(chunk_size=1024):
        f_zip.write(chunk)

这将显示:

Downloading: '286316.zip'

并生成一个 29,464,299 字节的 zip 文件。

【讨论】:

    【解决方案2】:

    您可以使用 BeautifulSoup 读取 HTML 页面标题中的元标记并获取重定向 URL,例如

    >>> import requests
    >>> from bs4 import BeautifulSoup
    >>> a = requests.get("http://www.vbb.de/de/datei/GTFS_VBB_Nov2015_Dez2016.zip")
    >>> soup = BeautifulSoup(a.text, 'html.parser')
    >>> soup.find_all('meta', attrs={'http-equiv': lambda x:x.lower() == 'refresh'})[0]['content'].split('URL=')[1]
    '/de/download/GTFS_VBB_Nov2015_Dez2016.zip'
    

    此 URL 将与原始 URL 的域相关,从而使新 URL http://www.vbb.de/de/download/GTFS_VBB_Nov2015_Dez2016.zip。下载这个似乎是为我下载 ZIP 文件:

    >>> a = requests.get("http://www.vbb.de/de/download/GTFS_VBB_Nov2015_Dez2016.zip", stream=True)
    >>> with open('test.zip', 'wb') as f:
    ...     a.raw.decode_content = True
    ...     shutil.copyfileobj(a.raw, f)
    ...
    

     $ unzip -l test.zip
    Archive:  test.zip
      Length      Date    Time    Name
    ---------  ---------- -----   ----
         5554  2015-11-20 15:17   agency.txt
      2151517  2015-11-20 15:17   calendar_dates.txt
        71731  2015-11-20 15:17   calendar.txt
        65424  2015-11-20 15:17   routes.txt
       816498  2015-11-20 15:17   stops.txt
    196020096  2015-11-20 15:17   stop_times.txt
       365499  2015-11-20 15:17   transfers.txt
     11765292  2015-11-20 15:17   trips.txt
          113  2015-11-20 15:17   logging
    ---------                     -------
    211261724                     9 files
    

    在此重定向上返回 301 状态:

    >>> a.history
    [<Response [301]>]
    >>> a
    <Response [200]>
    >>> a.history[0]
    <Response [301]>
    >>> a.history[0].url
    'http://www.vbb.de/de/download/GTFS_VBB_Nov2015_Dez2016.zip'
    >>> a.url
    'http://images.vbb.de/assets/ftp/file/286316.zip'
    

    【讨论】:

    • 这又是起始链接,只是解析并没有给我输出链接,因为它不在link的源代码中。我需要以某种方式从服务器响应中检索结果链接link
    • @Dmitri - 正如我在附加部分中展示的那样,您确实可以使用获得的链接下载文件 - 这对您的目的来说还不够吗?您的目标肯定是下载文件吗?
    • @Dmitri 手动重定向后,返回 301 状态,您将被重定向到文件的真实位置 - 请参阅我对答案的最后补充
    • 很遗憾,这还不够,我真的需要第二个链接
    • @Dmitri 查看之前的评论和对答案的补充
    猜你喜欢
    • 2017-03-25
    • 2021-03-21
    • 2018-10-30
    • 2011-09-21
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多