首页 > 解决方案 > 有没有办法使用 Python 从“网站按钮单击”下载 csv 文件?

问题描述

我想"Projects.csv"从这个网站自动下载 CSV 文件:

https://www.vcsprojectdatabase.org/#/projects/st_/c_/ss_0/so_/di_/np_

可以通过单击 CSV 图标手动下载 CSV,但我不确定如何在 python 中自动下载并将 CSV 文件本地存储在我的驱动器上。

到目前为止,我已经尝试通过 chrome 开发人员控制台检查按钮元素,以在“网络”选项卡中找到正确的 url,就像这样?

https://www.vcsprojectdatabase.org/services/publicViewServices/fetchProjectsExport

但我不确定这个 URL 是否应该在末尾包含文件名,如下所示:

https://www.vcsprojectdatabase.org/services/publicViewServices/fetchProjectsExport/Projects.csv

这是我尝试过的,但它只是写了一个空白文件:

import requests

url = 'https://www.vcsprojectdatabase.org/services/publicViewServices/fetchProjectsExport/Projects.csv'

r = requests.get(url)
with open('a.csv', 'wb') as f:
    f.write(r.content) 

如何让 CSV 文件正确下载和保存?

标签: javascriptpythonurl

解决方案


首先,你应该了解基于requests的 HTTP 协议。JavaScript 执行的最终结果将形成 HTTP 请求,让服务器响应文件内容。您需要“反转”网页,找到如何创建正确的请求并尽可能地重复它。

所以,让我们尝试一步一步地做到这一点:

  1. 在执行下载的元素上单击鼠标右键,然后按“检查元素” 在此处输入图像描述
  2. 在源代码中,您可以看到此元素执行的 JavaScript 函数的名称 在此处输入图像描述
  3. 在不带括号的控制台中键入函数名称,然后单击应出现在控制台返回附近的按钮(此按钮将在源代码中打开此 JavaScript 函数) 在此处输入图像描述
  4. 在源代码中,我们看到该函数在具有 id 的 HTML 元素上执行提交frmDownload。因此,返回“Inspector”选项卡并在搜索框中输入此 ID。 在此处输入图像描述
  5. 现在我们发现这个元素是 HTML表单。此表单将POST请求发送到https://www.vcsprojectdatabase.org/services/publicViewServices/fetchProjectsExport带有下一个数据的 URL:

    searchTerm=
    country=
    sectoral_scope=0
    recentProjects=
    sort=projectId
    dir=DESC
    formatType=csv
    

    此信息足以尝试在 Python 中重复此请求。

让我们编写一个小脚本,形成并发送相同的请求并将结果保存到 .csv 文件中:

import requests

data = {
    "searchTerm": "",
    "country": "",
    "sectoral_scope": "0",
    "recentProjects": "",
    "sort": "projectId",
    "dir": "DESC",
    "formatType": "csv"
}

file = requests.post("https://www.vcsprojectdatabase.org/services/publicViewServices/fetchProjectsExport", data)

with open("res.csv", "wb+") as f:
    f.write(file.content)

启动它,它......工作。res.csv包含正确的结果。

但这还不是全部。通常一切都不是那么容易。为了让我们的请求看起来与浏览器发送的相同,我们应该查看请求标头。要从浏览器捕获 HTTP 请求,我们可以打开“网络”选项卡:

在此处输入图像描述

现在让我们按网页上的下载按钮并下载 csv 文件。现在在 requests 表中,我们可以看到我们的 post 请求。单击它并查看“请求标头”部分中的“标头”选项卡。

在此处输入图像描述

Cookie头,大部分在请求中并不重要,可以忽略。但是,如果您对请求有一些问题,您应该查看以前的请求,Set-Cookie在服务器响应中找到带有标头的请求并重复它。

让我们改进我们的脚本并从浏览器复制重要的(主机、内容长度、连接我们不包括,因为 Python 请求模块会自动添加它们;根本不需要 DNT 和升级不安全请求)标头。

import requests

data = {
    "searchTerm": "",
    "country": "",
    "sectoral_scope": "0",
    "recentProjects": "",
    "sort": "projectId",
    "dir": "DESC",
    "formatType": "csv"
}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language":  "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
    "Referer": "https://www.vcsprojectdatabase.org/",
    "Content-Type": "application/x-www-form-urlencoded"
}

file = requests.post("https://www.vcsprojectdatabase.org/services/publicViewServices/fetchProjectsExport", data,
                     headers=headers)

with open("res.csv", "wb+") as f:
    f.write(file.content)

PS不要忘记向网站所有者征求许可


推荐阅读