【问题标题】:Download Specific file from Website with BeautifulSoup使用 BeautifulSoup 从网站下载特定文件
【发布时间】:2021-02-10 18:01:20
【问题描述】:

按照 BeautifulSoup 的文档,我正在尝试从网页下载特定文件。首先尝试找到包含文件名的链接:

import re
import requests
from bs4 import BeautifulSoup

url = requests.get("https://www.bancentral.gov.do/a/d/2538-mercado-cambiario")
parsed = BeautifulSoup(url.text, "html.parser")
link = parsed.find("a", text=re.compile("TASA_DOLAR_REFERENCIA_MC.xls"))
path = link.get('href')
print(f"{path}")

但没有成功。然后尝试打印该页面上的每个链接,我没有得到任何链接:

import re
import requests
from bs4 import BeautifulSoup

url = requests.get("https://www.bancentral.gov.do/a/d/2538-mercado-cambiario")
parsed = BeautifulSoup(url.text, "html.parser")
link = parsed.find_all('a')
for links in parsed.find_all("a href"):
    print(links.get('a href'))

看起来文件的url是动态的,它在url的末尾添加了一个?v=123456789参数,就像文件版本一样,所以我需要使用文件名下载文件。

(例如https://cdn.bancentral.gov.do/documents/estadisticas/mercado-cambiario/documents/TASA_DOLAR_REFERENCIA_MC.xls?v=1612902983415

谢谢。

【问题讨论】:

  • link = parsed.find_all('a') 从未使用过。但这没关系,因为您想要的数据不在 HTML 中。您加载的页面会触发一个请求,该请求使用有效负载 id=2538&languageName=es 命中 bancentral.gov.do/Home/GetContentForRender 以获取包含 xlses 的 HTML 内容,但这些没有 v= 键,所以我假设这是由 JS 添加的。所有这些链接都具有完全相同的密钥,而且看起来并不重要——我可以使用 GET 直接访问文件,而不需要 v=。长话短说,你可以直接从 URL 下载文件,不是吗?
  • 你是对的@ggorlen。!我

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


【解决方案1】:

实际上,您正在处理一个 dynamic JavaScript 页面,该页面在页面加载后通过XHR 请求完全加载到以下url

下面是对后端 API 的直接调用,该 API 使用页面 ID(2538)识别请求,然后我们可以加载您想要的 URL。

import requests
from bs4 import BeautifulSoup


def main(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0'
    }
    with requests.Session() as req:
        req.headers.update(headers)
        data = {
            "id": "2538",
            "languageName": "es"
        }
        r = req.post(url, data=data)
        soup = BeautifulSoup(r.json()['result']['article']['content'], 'lxml')
        target = soup.select_one('a[href*=TASA_DOLAR_REFERENCIA_MC]')['href']
        r = req.get(target)
        with open('data.xls', 'wb') as f:
            f.write(r.content)


if __name__ == "__main__":
    main('https://www.bancentral.gov.do/Home/GetContentForRender')

【讨论】:

    猜你喜欢
    • 2020-08-02
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    相关资源
    最近更新 更多