Загрузка определенного файла с веб-сайта с помощью BeautifulSoup

#python-3.x #beautifulsoup #python-requests

#python-3.x #beautifulsoup #python-запросы

Вопрос:

Следуя документации 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-адрес файла является динамическим, он добавляет параметр ?v = 123456789 в конец URL-адреса, например, версию файла, поэтому мне нужно загрузить файл, используя имя файла.

(Например https://cdn.bancentral.gov.do/documents/estadisticas/mercado-cambiario/documents/TASA_DOLAR_REFERENCIA_MC.xls?v=1612902983415)

Спасибо.

Комментарии:

1. link = parsed.find_all('a') никогда не используется. Но это не имеет значения, потому что нужные вам данные отсутствуют в HTML. Загруженная вами страница отправляет запрос, который попадает bancentral.gov.do/Home/GetContentForRender с идентификатором полезной нагрузки = 2538amp;languageName = es, чтобы получить HTML-содержимое, содержащее xlse, но у них нет ключа v =, поэтому я предполагаю, что это добавляется JS. Все эти ссылки имеют один и тот же ключ, и, похоже, это не имеет значения — я могу получить доступ к файлу напрямую, перейдя по URL-адресу без v= . Короче говоря, вы можете просто загрузить файл непосредственно с URL-адреса, нет?

2. Вы правы @ggorlen.! Я

Ответ №1:

На самом деле вы имеете дело со dynamic JavaScript страницей, которая полностью загружается с помощью XHR запроса на следующий URL-адрес после загрузки страницы.

Ниже приведен прямой вызов внутреннего API, который идентифицирует запрос, используя идентификатор страницы, который является 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')