从依赖于交互式地图的表中收集数据

时间:2018-07-24 13:31:55

标签: python python-3.x selenium selenium-webdriver web-scraping

另一个搜寻问题。我正在尝试从以下网站抓取数据: https://www.flightradar24.com/data/airlines/kl-klm/routes

但是,我要获取的数据仅在您单击其中一个机场后以地图下方表格的形式显示。从此表中,我想提取一个数字,该数字指示每天飞往每个机场的航班的频率。例如,如果您点击巴黎戴高乐机场,然后从表格中查看荷兰国家,则该行在上一行显示 td rowspan =“ 6” ,在这种情况下,这表明荷航有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 个答案:

答案 0 :(得分:3)

尝试使用直接的HTTP请求获取所需的数据,而不是使用Selenium:

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>

要从arrRoutes变量获取JSON:

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"])

答案 1 :(得分:1)

该地图没有通过HTML / CSS表示,因此我认为不可能通过Selenium与之交互。

但是,我偶然发现了Sikuli API,它可以使图像识别与Google Maps(如您链接的页面上),验证码等互动... ...您可以裁剪该标记并尝试使用Sikuli进行识别然后点击它。有关使用方法的小示例,请参见http://www.assertselenium.com/maven/sikuliwebdriver-2/

但是,可以使用Xpath轻松选择表中的数据,并使用Selenium之类的工具进行解析。但是,似乎Sikuli仅在Java中可用,因此您也必须在Java中使用Selenium。

答案 2 :(得分:0)

您可以使用Kantu Selenium IDE,它可以执行以下操作:

  • 使用image search

  • 直观地找到标记
  • 使用Click #efp单击标记<=这在画布内有效

  • Web使用xpath和经典的Selenium IDE命令(例如storeText

  • )来抓取表格

您仍然需要解决的问题是如何单击地图上的所有点(机场)。如果您要使用Sikuli,那就是同样的挑战。

更新:实际上,我认为您可以通过不使用图像识别来解决此问题,而使用ClickAt“愚蠢”地单击地图中的每个点(可能每3像素左右)。然后,在世界范围内,您将拥有所有的机场。