用Python下载文件(带请求?)

用Python下载文件(带请求?),python,beautifulsoup,web-crawler,python-requests,Python,Beautifulsoup,Web Crawler,Python Requests,我想做的是建立一个简单的爬虫来帮助我从Ultimate吉他下载吉他标签。我可以为它提供一个乐队的URL,它会抓取所有标签的链接,这些标签被列为“吉他专业”标签 典型的链接如下所示: import cgi import requests import shutil def download_url(url, directory): """Download file from url to directory URL is expected to have a Content-D

我想做的是建立一个简单的爬虫来帮助我从Ultimate吉他下载吉他标签。我可以为它提供一个乐队的URL,它会抓取所有标签的链接,这些标签被列为“吉他专业”标签

典型的链接如下所示:

import cgi
import requests
import shutil

def download_url(url, directory):
    """Download file from url to directory

    URL is expected to have a Content-Disposition header telling us what
    filename to use.

    Returns filename of downloaded file.

    """
    response = requests.get(url, stream=True)
    if response.status != 200:
        raise ValueError('Failed to download')

    params = cgi.parse_header(
        response.headers.get('Content-Disposition', ''))[-1]
    if 'filename' not in params:
        raise ValueError('Could not find a filename')

    filename = os.path.basename(params['filename'])
    abs_path = os.path.join(directory, filename)
    with open(abs_path, 'wb') as target:
        response.raw.decode_content = True
        shutil.copyfileobj(response.raw, target)

    return filename

我可以使用此链接使用以下代码查找选项卡id:

for tabid in tab.findAll("input", {"type" : "hidden", "name" : "id", "id" : "tab_id"}):
        tabID = tabid.get("value")
我想做的是用它来建立一个链接到实际下载。我遇到问题的地方就在这里。我可以构建的最佳链接如下所示:

import cgi
import requests
import shutil

def download_url(url, directory):
    """Download file from url to directory

    URL is expected to have a Content-Disposition header telling us what
    filename to use.

    Returns filename of downloaded file.

    """
    response = requests.get(url, stream=True)
    if response.status != 200:
        raise ValueError('Failed to download')

    params = cgi.parse_header(
        response.headers.get('Content-Disposition', ''))[-1]
    if 'filename' not in params:
        raise ValueError('Could not find a filename')

    filename = os.path.basename(params['filename'])
    abs_path = os.path.join(directory, filename)
    with open(abs_path, 'wb') as target:
        response.raw.decode_content = True
        shutil.copyfileobj(response.raw, target)

    return filename

请注意,该URL末尾的id是我之前提到的选项卡id

如果输入到浏览器中,此链接将立即导致下载。我遇到的问题是,我找不到任何方法来生成依赖于实际文件名的链接。此文件名应类似于[song name here].gp5。其他可接受的文件类型可以是.gpx、.gp4和.gp3

我想做的是获得实际的文件名,这样我就可以正确地保存文件(如果下载的文件被命名为垃圾文件,比如ID,这对我没有帮助,因为这对我来说是一个无用的文件名,我显然需要正确的扩展名)。有没有什么方法可以获取上面的链接并正确初始化下载,或者我在这方面运气不佳?我确信有一种方法可以满足我的需要,我只是在这方面没有足够的经验。我对请求之类的东西一无所知,所以也许有可能在这个URL上输入一些东西,然后得到下载作为回报


注意:如果很难获得实际的文件名和扩展名,我确实有解决方法,但我显然至少需要适当的扩展名。

响应的标题中包含文件名。您可以使用解析标题中的这些内容,并使用它们保存文件:

>>> import requests
>>> r = requests.get('https://tabs.ultimate-guitar.com/tabs/download?id=904610')
>>> r.headers['Content-Disposition']
'attachment; filename="Agalloch - You Were But A Ghost In My Arms (Pro).gp5"'
>>> cgi.parse_header(r.headers['Content-Disposition'])[-1]['filename']
'Agalloch - You Were But A Ghost In My Arms (Pro).gp5'
完成下载的完整功能可能如下所示:

import cgi
import requests
import shutil

def download_url(url, directory):
    """Download file from url to directory

    URL is expected to have a Content-Disposition header telling us what
    filename to use.

    Returns filename of downloaded file.

    """
    response = requests.get(url, stream=True)
    if response.status != 200:
        raise ValueError('Failed to download')

    params = cgi.parse_header(
        response.headers.get('Content-Disposition', ''))[-1]
    if 'filename' not in params:
        raise ValueError('Could not find a filename')

    filename = os.path.basename(params['filename'])
    abs_path = os.path.join(directory, filename)
    with open(abs_path, 'wb') as target:
        response.raw.decode_content = True
        shutil.copyfileobj(response.raw, target)

    return filename

文件名包含在响应的标题中。您可以使用解析标题中的这些内容,并使用它们保存文件:

>>> import requests
>>> r = requests.get('https://tabs.ultimate-guitar.com/tabs/download?id=904610')
>>> r.headers['Content-Disposition']
'attachment; filename="Agalloch - You Were But A Ghost In My Arms (Pro).gp5"'
>>> cgi.parse_header(r.headers['Content-Disposition'])[-1]['filename']
'Agalloch - You Were But A Ghost In My Arms (Pro).gp5'
完成下载的完整功能可能如下所示:

import cgi
import requests
import shutil

def download_url(url, directory):
    """Download file from url to directory

    URL is expected to have a Content-Disposition header telling us what
    filename to use.

    Returns filename of downloaded file.

    """
    response = requests.get(url, stream=True)
    if response.status != 200:
        raise ValueError('Failed to download')

    params = cgi.parse_header(
        response.headers.get('Content-Disposition', ''))[-1]
    if 'filename' not in params:
        raise ValueError('Could not find a filename')

    filename = os.path.basename(params['filename'])
    abs_path = os.path.join(directory, filename)
    with open(abs_path, 'wb') as target:
        response.raw.decode_content = True
        shutil.copyfileobj(response.raw, target)

    return filename

当您在下载链接上发出HEAD请求而不是get请求时,您是否获得了有用的信息?您是否签出了此问题?当您在下载链接上发出HEAD请求而不是get请求时,您是否获得了有用的信息?您是否签出了此问题?谢谢你的帮助!根据我的原始帖子上面的评论,我设法找到了文件名并使用正则表达式将其隔离,但我更喜欢你的方法。我还要感谢您的文件输出,因为我尝试的原始方法(在我看到您的编辑包含文件输出之前)不太有效。谢谢您的帮助!根据我的原始帖子上面的评论,我设法找到了文件名并使用正则表达式将其隔离,但我更喜欢你的方法。我还要感谢您的文件输出,因为我尝试的原始方法(在我看到您的编辑包含文件输出之前)不太管用。