Веб-скрапинг Python с данными, полученными из javascripts

Я хочу собрать данные с веб-сайта (https://nextgenftl.com/leagues/ftl-main-2022/game-weeks/week-30/players), созданного с помощью javascript. Я хочу получить всех игроков, а также значок, цену и изменение цены каждого игрока. Как получить все данные с веб-сайта после его рендеринга?

Я пытаюсь отобразить всю страницу (включая скрипты) перед очисткой.

from requests_html import HTMLSession
from bs4 import BeautifulSoup

# Assign the URL,
# create the HTMLSession object,
# and run the "get" method to retrieve information from the URL
week = 30
url = f'https://nextgenftl.com/leagues/ftl-main-2022/game-weeks/week-{week}/players'
session = HTMLSession()
response = session.get(url)

# Check that the resolution code was 200
# (successfully retrieved info from URL)
res_code = response.status_code
print(res_code)
if res_code == 200:
    response.html.render() # This is the critical line. This render method runs the script tags to turn them into HTML

    # Get the page content
    soup = BeautifulSoup(response.content, 'lxml')
    print(soup.prettify())
    
else:
    print("Could not reach web page!")

Я не мог использовать BS4, потому что исходный код страницы не содержит тела (все тело визуализируется из javascript). Кроме того, я просмотрел вкладку сети, чтобы увидеть, какие API выдают данные, но это не сработало. Я также пробовал с селеном, но я до сих пор не знаю, как очистить данные с веб-сайта.

Что вы пробовали с Selenium?

Barry the Platipus 19.11.2022 11:11
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
0
1
86
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вот один из способов получить эту информацию с помощью Selenium. Это не быстро, но надежно и возвращает всех игроков (725). Настройка Selenium — это chromedriver/linux, вы можете адаптировать ее к своей собственной настройке, просто наблюдайте за импортом и кодом после определения драйвера.

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

pd.set_option('display.max_columns', None)
pd.set_option('display.max_colwidth', None)

chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument('disable-notifications')
chrome_options.add_argument("window-size=1280,720")

webdriver_service = Service("chromedriver/chromedriver") ## path to where you saved chromedriver binary
driver = webdriver.Chrome(service=webdriver_service, options=chrome_options)
wait = WebDriverWait(driver, 25)
url = 'https://nextgenftl.com/leagues/ftl-main-2022/game-weeks/week-30/players'
big_list = []
driver.get(url)

for x in range(10):
    players = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//ion-list[not(@id="menu-list")]//ion-item')))
    for p in players:
        p.location_once_scrolled_into_view
    wait.until(EC.presence_of_element_located((By.TAG_NAME, 'ion-infinite-scroll'))).location_once_scrolled_into_view
    
    t.sleep(1)
players = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//ion-list[not(@id="menu-list")]//ion-item')))
for p in players:
    try:
        p.location_once_scrolled_into_view
        badge = p.find_element(By.XPATH, './/ion-badge').text
        name = p.find_element(By.XPATH, './/ion-label').text
        current_price = p.find_element(By.XPATH, './/div[@title="Current Price"]').text
        price_change = p.find_element(By.XPATH, './/div[@title="Price Change"]').text
        average_points = p.find_element(By.XPATH, './/div[@title="3-Week Average Points"]').text
        events_played = p.find_element(By.XPATH, './/div[@title="Events Played"]').text
        
        big_list.append((badge, name, current_price, price_change, average_points, events_played))
    except Exception as e:
        print('error')
        continue
t.sleep(2)
print(len(big_list))
df = pd.DataFrame(big_list, columns = ['badge', 'name', 'current_price', 'price_change', 'average_points', 'events_played'])
print(df)
df.to_csv('fantasy_tennis.csv')

Это отобразит фрейм/таблицу данных в терминале, а также сохранит его как csv:

725
badge   name    current_price   price_change    average_points  events_played
0   ATP Novak Djokovic  $19.864m    --  116.97  7
1   ATP Rafael Nadal    $19.295m    ↓ 1.137 53.92   9
2   WTA Iga Swiatek $17.835m    ↓ 0.074 72.70   13
3   WTA Ashleigh Barty  $16.800m    --  169.50  1
4   ATP Carlos Alcaraz  $15.587m    ↑ 0.494 74.14   14
... ... ... ... ... ... ...
720 WTA Dayana Yastremska   $1.450m ↓ 0.068 3.75    14
721 WTA Xiaodi You  $1.450m --  3.77    1
722 WTA Eleana Yu   $1.450m --  2.90    1
723 WTA Anastasia Zakharova $1.450m --  1.77    1
724 ATP Kacper Zuk  $1.450m --  4.16    1

См. документацию по Selenium на https://www.selenium.dev/documentation/

Большое спасибо. Я знаю, где мне нужно добавить, я должен вызвать time.sleep, чтобы страница была полностью отображена.

Lucas 22.11.2022 17:36

Не за что @Лукас. Если мой ответ решил вашу проблему, не забудьте отметить его как принятый (зеленая галочка под кнопками голосования). И нет, это не только звонки time.sleep. Это также касается элементов, которые прокручиваются в поле зрения... просто следуйте моему коду.

Barry the Platipus 22.11.2022 17:38

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