Очистка данных из таблиц в зависимости от интерактивной карты

Еще один скребущий вопрос. Я пытаюсь собрать данные со следующего веб-сайта: https://www.flightradar24.com/data/airlines/kl-klm/routes

Однако данные, которые я хочу получить, отображаются только после нажатия на один из аэропортов в виде таблицы под картой. Из этой таблицы я хочу извлечь число, указывающее частоту ежедневных рейсов в каждый аэропорт. Например, если вы нажмете на Париж Шарль де Голль и осмотрите страну Нидерланды из таблицы, в строке выше будет показано td rowspan="6", что в данном случае означает, что KLM выполняет 6 рейсов в день в Париж.

Я предполагаю, что мне нужно будет использовать сеанс браузера, например, Selenium или что-то подобное, поэтому я начал со следующего кода, но я не уверен, куда идти дальше, так как не могу найти точки аэропорта в исходный код.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.binary_location = 'C:/Users/C55480/AppData/Local/Google/Chrome SxS/Application/chrome.exe'

driver = webdriver.Chrome(executable_path='C:/Users/C55480/.spyder-py3/going_headless/chromedriver.exe', chrome_options=chrome_options)

airlines = ['kl-klm', 'dy-nax', 'lh-dlh']

for a in airlines:
    url = 'https://www.flightradar24.com/data/airlines/' + a + '/routes'
    page = driver.get(url)

Есть ли способ заставить Selenium щелкнуть по каждой точке и определить количество ежедневных рейсов для каждого аэропорта, а затем найти общее количество ежедневных рейсов в каждую страну?

3 ответа

Решение

Вместо того, чтобы использовать Selenium, попробуйте получить необходимые данные с помощью прямых HTTP-запросов:

import requests
import json

s = requests.session()
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0"}
r = s.get("https://www.flightradar24.com/data/airlines/kl-klm/routes", headers=headers)

Данные для каждого аэропорта можно найти в скрипте узла, который выглядит как

<script>var arrRoutes=[{"airport1":{"country":"Denmark","iata":"AAL","icao":"EKYT","lat":57.092781,"lon":9.849164,"name":"Aalborg Airport"}...]</script>

Чтобы получить JSON от arrRoutes переменная:

my_json = json.loads(r.text.split("arrRoutes=")[-1].split(", arrDates=")[0])

Вам необходимо получить сокращение (значение для "iata" ключ) для каждого аэропорта:

abbs_list = []
for route in my_json:
    if route["airport1"]["country"] == "Netherlands":
        abbs_list.append(route["airport2"]["iata"])

Выход из print(abbs_list) должно быть как ['AAL', 'ABZ'...]

Теперь мы можем запросить данные для каждого аэропорта:

url = "https://www.flightradar24.com/data/airlines/kl-klm/routes?get-airport-arr-dep={}"
for abbr in abbs_list:
    cookie = r.cookies.get_dict()
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0",
               "Content-Type": "application/json",
               "x-fetch": "true"}
    response = s.get(url.format(abbr), cookies=cookie, headers=headers).json()
    print(abbr, ": ", response["arrivals"]["Netherlands"]["number"]["flights"])

Карта не представлена ​​в HTML/CSS, поэтому я не думаю, что с ней можно взаимодействовать через Selenium.

Однако я наткнулся на API Sikuli, который позволяет распознаванию изображений взаимодействовать с Картами Google (как на странице, на которую вы ссылаетесь), капчами... Вы можете обрезать этот маркер и попытаться использовать Sikuli для его распознавания и щелкнуть по нему. См. http://www.assertselenium.com/maven/sikuliwebdriver-2/ для небольшого примера того, как его использовать.

Однако данные в таблицах можно легко выбрать с помощью Xpath и проанализировать с помощью такого инструмента, как Selenium. Однако кажется, что Sikuli можно использовать только в Java, поэтому вам придется использовать Selenium и Java.

Вы можете использовать Kantu Selenium IDE, он может делать следующее:

  • Визуально найдите маркер, используя поиск изображений

  • Нажмите на маркер, используя Click #efp <= это работает внутри холста

  • Веб-очистка таблицы с использованием xpath и классических команд Selenium IDE, таких как storeText

Проблема, которую вам еще нужно решить, состоит в том, как щелкнуть все точки (аэропорты) на карте. Это та же проблема, что и у вас, если вы будете использовать Sikuli.

Обновление: на самом деле, я думаю, что вы можете решить эту проблему, не используя распознавание изображений, а "тупо", используя ClickAt, чтобы кликать в любой точке карты (возможно, каждый третий пиксель или около того). Тогда, по мировоззрению, у вас будут все аэропорты.

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