如何通过身份验证下载文件?

时间:2019-01-15 17:02:02

标签: python python-3.x authentication python-requests

我正在使用网站“ musescore.com”,该网站包含许多“ .mxl”格式的文件,需要使用Python自动下载。

网站上的每个文件都有唯一的ID号。这是一个示例文件的链接:

https://musescore.com/user/43726/scores/76643

URL中的最后一个数字是此文件的ID号。我不知道分数的mxl文件在网站上的哪个位置,但是我知道要下载该文件,必须访问此URL:

https://musescore.com/score/76643/download/mxl

每个文件的此链接都相同,但是其中包含该文件的特定ID号。据我了解,此url执行下载文件的代码,而不是文件的实际路径。

这是我的代码:

import requests

url = 'https://musescore.com/score/76643/download/mxl'
user = 'myusername'
password = 'mypassword'

r = requests.get(url, auth=(user, password), stream=True)
with open('file.mxl', 'wb') as f:
  for chunk in r.iter_content(chunk_size=1024):
    f.write(chunk)

此代码下载一个网页,说我需要登录才能下载文件。应该为此分数下载mxl文件。这必须表示我对网站进行了不正确的身份验证。我该如何解决?

1 个答案:

答案 0 :(得分:0)

通过将auth参数传递给get,您正在尝试利用HTTP Basic Authentication,这不是该特定站点所使用的。您需要使用request.Session的实例来发布到他们的登录端点并维护该过程产生的cookie。

此外,该网站还使用了csrf令牌,您必须首先从登录页面中提取该令牌,以便将其包含在发布到登录端点的帖子中。

这是一个有效的示例,显然您需要将用户名和密码更改为您自己的用户名:

import requests
from bs4 import BeautifulSoup

s = requests.Session()
r = s.get('https://musescore.com/user/login')

soup = BeautifulSoup(r.content, 'html.parser')
csrf = soup.find('input', {'name': '_csrf'})['value']

s.post('https://musescore.com/user/auth/login/process', data={
    'username': 'herp@derp.biz',
    'password': 'secret',
    '_csrf': csrf,
    'op': 'Log in'
})

r = s.get('https://musescore.com/score/76643/download/mxl')

print(f"Status: {r.status_code}")
print(f"Content-Type: {r.headers['content-type']}")

结果,内容类型显示为正在成功下载文件:

Status: 200
Content-Type: application/vnd.recordare.musicxml