Как очистить таблицу csv, содержащуюся внутри кнопки JavaScript, с помощью Python?

Я пытаюсь перетащить таблицу csv с веб-страницы в фрейм данных pandas в блокноте Jupyter - процесс, который я успешно реализовал несколько раз в прошлом для других веб-сайтов, но с этим я столкнулся с проблемой.

Таблица, которую я пытаюсь получить, доступна только как ответ JavaScript на нажатие кнопки, а не по определенному URL-адресу.

Вот URL-адрес: https://ciffc.net/national // Таблица, которую я пытаюсь очистить, находится внутри кнопки «Экспорт» (CSV), выделенной красным.

Я попытался реализовать решение с помощью pandas.read_csv, но не могу указать на нужную кнопку.

Следует отметить, что я использую Jupyter Notebooks в среде ArcGIS Online.

Спасибо!

Чем это отличается от других ваших усилий? «Я пытаюсь перетащить таблицу csv с веб-страницы в фрейм данных pandas в блокноте Jupyter — процесс, который я успешно реализовал несколько раз в прошлом для других веб-сайтов, но с этим я столкнулся с проблемой». Поделитесь примерами кода и как вы пытались их адаптировать? Единственное, что я вижу здесь, это то, что это динамическая страница, а не статическая, поэтому вы не просто получаете URL-адрес. Но поскольку у вас нет кода, я не могу сказать, знаете ли вы это уже?

Wayne 14.06.2024 23:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
84
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

JSON, например, для страницы 1, кажется, доступен по стабильному URL-адресу https://api.ciffc.net//v1/wildfires?page=1.

Итак, если вы не против выполнить дополнительное форматирование DataFrame, вы можете использовать:

import pandas
import requests

df = pandas.DataFrame.from_dict(
    requests.get('https://api.ciffc.net//v1/wildfires?page=1').json()["rows"])

Который содержит:

field_agency_fire_id field_agency_code field_agency_data_timezone field_situation_report_date field_status_date field_stage_of_control_status field_system_fire_cause field_response_type field_fire_size поле_широта поле_долгота полный_счет 0 СС007-24 нт МДТ 2024-05-12T22:21:00.000Z 2024-06-14T20:00:10.000Z ОК Н ПН 1 60,5853 -116,902 1515 1 ФС005-24 нт МДТ 2024-05-13T17:40:00.000З 2024-06-14T20:00:10.000Z Калифорнийский университет Н ПОЛНЫЙ 22 61,52 -121,393 1515 2 СС015-24 нт МДТ 2024-06-01T21:57:00.000З 2024-06-14T20:00:10.000Z ОК Н ПОЛНЫЙ 0,2 60.0809 -117,185 1515 3 СС008-24 нт МДТ 2024-05-23T23:24:00.000Z 2024-06-14T20:00:10.000Z ОК Н ПН 8 60.2382 -118,13 1515 4 СС003-24 нт МДТ 2024-05-05T19:45:00.000З 2024-06-14T20:00:10.000Z ВНЕ Н ПОЛНЫЙ 0,01 60,6161 -116,073 1515 5 ФС006-24 нт МДТ 2024-05-13T21:47:00.000З 2024-06-14T20:00:10.000Z ОК Н ПН 29:30 61,2465 -119,392 1515 6 ZF004-24 нт МДТ 2024-05-25T17:55:00.000З 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0 62.4502 -114,401 1515 7 ZF001-24 нт МДТ 2024-02-05T15:00:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0,05 62.3217 -114,252 1515 8 СС012-24 нт МДТ 2024-05-25T18:00:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0,1 61.1722 -113,669 1515 9 СС009-24 нт МДТ 2024-05-24T16:08:00.000З 2024-06-14T20:00:10.000Z ОК Н МОД 5681 60 -117 1515 10 СС005-24 нт МДТ 2024-05-10T20:10:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0,5 60,5885 -116,176 1515 11 СС004-24 нт МДТ 2024-05-05T20:45:00.000Z 2024-06-14T20:00:10.000Z ЧД Н ПОЛНЫЙ 3 60,3924 -117,896 1515 12 СС002-24 нт МДТ 2024-04-23T06:00:00.000Z 2024-06-14T20:00:10.000Z ВНЕ Н ПОЛНЫЙ 0,5 60,3258 -112,282 1515 13 СС001-24 нт МДТ 2024-04-23T06:00:00.000Z 2024-06-14T20:00:10.000Z ВНЕ Н ПОЛНЫЙ 2 60.119 -112,281 1515 14 ZF007-24 нт МДТ 2024-06-06T22:37:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0 62,5128 -113,694 1515 15 ZF005-24 нт МДТ 2024-05-26T13:00:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0 62,5185 -114,319 1515 16 ZF003-24 нт МДТ 2024-05-23T23:30:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 5 63,4575 -116,098 1515 17 ZF002-24 нт МДТ 2024-05-19T23:45:00.000Z 2024-06-14T20:00:10.000Z ВНЕ ЧАС ПОЛНЫЙ 0,01 62,4923 -113,521 1515 18 СС014-24 нт МДТ 2024-05-29T23:55:00.000Z 2024-06-14T20:00:10.000Z ВНЕ Н ПОЛНЫЙ 2,5 60.2638 -116,334 1515 19 СС013-24 нт МДТ 2024-05-27T20:18:00.000Z 2024-06-14T20:00:10.000Z ВНЕ Н ПОЛНЫЙ 0,5 60,3 -116,65 1515 20 СС011-24 нт МДТ 2024-05-24T18:40:00.000Z 2024-06-14T20:00:10.000Z ВНЕ Н ПОЛНЫЙ 1 60,9028 -112,421 1515 21 СС010-24 нт МДТ 2024-05-24T18:22:00.000Z 2024-06-14T20:00:10.000Z ОК Н МОД 28 60,9536 -112,39 1515 22 ZF006-24 нт МДТ 2024-05-31T21:49:00.000З 2024-06-14T20:00:10.000Z ОК Н ПН 145 62,5954 -119,058 1515 23 СС006-24 нт МДТ 2024-05-10T21:49:00.000Z 2024-06-14T20:00:10.000Z ВНЕ Н ПН 1 60,6623 -115,978 1515 24 ФС004-24 нт МДТ 2024-05-10T18:20:00.000Z 2024-06-14T20:00:10.000Z ОК Н МОД 11894 61.1473 -119,376 1515

Это работает для меня:

import requests
import pandas as pd

url = 'https://api.ciffc.net//v1/wildfires?export=true'
jsonData = requests.get(url).json()


# So want to skip `rows': [` part because the other part seems to have the column headers and data:
#solution to bypassing outer level from 
# answer to 'Remove outer array from JSON in Python dataframe' https://stackoverflow.com/a/69800668/8508004

d = requests.get(url).json()
#df = pd.DataFrame(json.loads(d)["rows"]) #if d is a string 
df = pd.DataFrame(jsonData["rows"]) #uncomment if d is not a string
df

Подробности:

Это были два основных ресурса, которые позволили объединить это:

Дайте мне знать, если вам нужны дополнительные разъяснения.

Я сделал это с помощью Selenium, используя некоторые ресурсы Javascript, как вы сказали, для загрузки файла нужно щелкнуть нижнюю часть с помощью JS. Нравиться:

def download_file(self):
    try:
        self.setup_driver()
        url = "https://ciffc.net/national"
        self._driver.get(url)
        
        wait = WebDriverWait(self._driver, 20)
        button_download = wait.until(
            EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'table-filter')]//button[contains(@class, 'button')]"))
        )
        
        self._driver.execute_script("arguments[0].click();", button_download)
        
        time.sleep(2)
        
        downloaded_file = self.get_downloaded_file_path()
        
        df = pd.read_csv(downloaded_file)
        print(df)
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        if self._driver:
            self._driver.quit()
            
def get_downloaded_file_path(self):
    files = os.listdir(os.getcwd())
    files.sort(key=lambda x: os.path.getmtime(x))
    return os.path.join(os.getcwd(), files[-1])

Этот код прост и отлично работает, чтобы найти элемент и выполнить щелчок, чтобы загрузить файл и преобразовать его в фрейм данных pandas. Здесь указана self._driver.execute_script("arguments[0].click();", button_download) деталь, которая необходима в таких ситуациях!

Весь код, если вам нужно:

from selenium import webdriver
import pandas as pd
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import 
expected_conditions as EC
from webdriver_manager.chrome import 
ChromeDriverManager
import os
import time

class FileHandlerX:
    def __init__(self) -> None:
        self._chrome_options = self.define_options()
        self._driver = None
    
    def define_options(self):
        chrome_options = Options()
        prefs = {
           "download.prompt_for_download": False,
           "download.directory_upgrade": True,
           "safebrowsing.enabled": True,
           "download.default_directory": os.getcwd()
        }
    chrome_options.add_experimental_option("prefs", 
    prefs)
    return chrome_options

   def setup_driver(self):
    chrome_service = 
 Service(ChromeDriverManager().install())
    self._driver = 
 webdriver.Chrome(service=chrome_service, 
 options=self._chrome_options)
    self._driver.implicitly_wait(10)

def download_file(self):
    try:
        self.setup_driver()
        url = "https://ciffc.net/national"
        self._driver.get(url)
        
        wait = WebDriverWait(self._driver, 20)
        button_download = wait.until(
            EC.element_to_be_clickable((By.XPATH, 
 "//div[contains(@class, 'table- 
  filter')]//button[contains(@class, 'button')]"))
        )
        
        
self._driver.execute_script("arguments[0].click();", 
button_download)
        
        time.sleep(2)
        
        downloaded_file = 
        self.get_downloaded_file_path()
        
        df = pd.read_csv(downloaded_file)
        print(df)
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        if self._driver:
            self._driver.quit()
            
    def get_downloaded_file_path(self):
        files = os.listdir(os.getcwd())
        files.sort(key=lambda x: os.path.getmtime(x))
        return os.path.join(os.getcwd(), files[-1])

if __name__ == "__main__":
    test = FileHandlerX()
    test.download_file()

Некоторые ресурсы о деталях: https://www.tutorialspoint.com/how-to-click-button-selenium-python и https://thewikihow.com/video_xhnOGgPrdj0?si=bshEDsk6ukzlRcEl

Другие вопросы по теме

Функция модели ARMA для будущих невидимых данных с датами начала и окончания?
Я продолжаю получать ошибку «функция не повторяется» с фильтром Pandas DataFrame, но та же функция работает с применением. Что мне не хватает?
Эффективный поиск значения столбца в столбце, содержащем списки, с помощью pandas
Сортировка месяцев внутри объекта Multi index groupby
Объединить/объединить несколько фреймов данных pandas со смешиванием значений в одном столбце
Создать фрейм данных из определенных XML-данных в Python
Невозможно преобразовать данные столбца и сохранить их в одном новом столбце в пандах фрейма данных
Замена значений NaN на ноль в функции слияния pandas с внешним соединением
Вывод ограничения скорости Pandas на основе минимального изменения в столбце
Каков наиболее эффективный способ заполнения нескольких столбцов значениями из других столбцов таким образом, чтобы их можно было соединить с суффиксом?