【问题标题】:How to scrape real time streaming data with Python?如何使用 Python 抓取实时流数据?
【发布时间】:2016-09-14 11:22:10
【问题描述】:

我正在尝试抓取此网页的航班数量https://www.flightradar24.com/56.16,-49.51

数字在下图中突出显示:

数字每 8 秒更新一次。

这是我用 BeautifulSoup 尝试的:

import requests
from bs4 import BeautifulSoup
import time

r=requests.get("https://www.flightradar24.com/56.16,-49.51")
c=r.content
soup=BeautifulSoup(c,"html.parser")
value=soup.find_all("span",{"class":"choiceValue"})
print(value)

但这总是返回 0:

[<span class="choiceValue" id="menuPlanesValue">0</span>]

查看源代码也显示0,所以我明白BeautifulSoup为什么也返回0了。

有谁知道获取当前值的其他方法吗?

【问题讨论】:

  • 我认为这些值是通过javascript更新的,并且在页面加载后,初始值为0。所以你需要在抓取内容之前以某种方式执行js。否则,你将永远得到零。
  • @linusg 有关如何做到这一点的任何线索?
  • 我是对的,看看@Andre 的回答!
  • 如果您有兴趣,我可以编写一些基本代码来检索 json 并对其进行处理...可能需要几分钟,但如果对您有帮助... :)
  • @linusg 谢谢。我正在尝试c=r.json()["list"],但得到了json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

标签: python web-scraping beautifulsoup


【解决方案1】:

您可以使用selenium 抓取带有javascript添加的动态内容的网页。

from bs4 import BeautifulSoup
from selenium import webdriver

browser = webdriver.PhantomJS()
browser.get('https://www.flightradar24.com/56.16,-49.51/3')

soup = BeautifulSoup(browser.page_source, "html.parser")
result = soup.find_all("span", {"id": "menuPlanesValue"})

for item in result:
    print(item.text)

browser.quit()

【讨论】:

    【解决方案2】:

    所以根据@Andre 的发现,我写了这段代码:

    import requests
    from bs4 import BeautifulSoup
    import time
    
    def get_count():
        url = "https://data-live.flightradar24.com/zones/fcgi/feed.js?bounds=59.09,52.64,-58.77,-47.71&faa=1&mlat=1&flarm=1&adsb=1&gnd=1&air=1&vehicles=1&estimated=1&maxage=7200&gliders=1&stats=1"
    
        # Request with fake header, otherwise you will get an 403 HTTP error
        r = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
    
        # Parse the JSON
        data = r.json()
        counter = 0
    
        # Iterate over the elements to get the number of total flights
        for element in data["stats"]["total"]:
            counter += data["stats"]["total"][element]
    
        return counter
    
    while True:
        print(get_count())
        time.sleep(8)
    

    代码应该是自我解释的,它所做的一切都是每 8 秒打印一次实际航班计数 :)

    注意: 这些值与网站上的值相似,但不一样。这是因为 Python 脚本和网站不太可能同时发送请求。如果您想获得更准确的结果,只需每 4 秒发出一次请求即可。

    根据需要使用此代码,扩展它或其他任何方式。希望这会有所帮助!

    【讨论】:

    • 为什么你会使用eval 而不是调用r.json()?或者至少打电话给json.loads(r.content) 这是r.json() 会做的事情。
    • @PadraicCunningham - 嗯,这只是我的第一个想法。正如我所写,代码并不是最终的:D
    • @linusg:非常有趣!确实正如您提到的,有时 Python 脚本中的值与网站不同。在这些情况下,Python 在做什么,它是在计算插值吗?
    • 呃,那是前段时间了。据我记得(!=AFAIR),数据是实时的,因此每次您提出请求时都会有所不同。正如我所写,Python 脚本和浏览器不会确切同时发出请求,这是因为值会在某种程度上有所不同。只需更频繁地发出请求即可获得与浏览器中类似的结果。不过应该没关系。
    【解决方案3】:

    您的方法的问题是页面首先加载一个视图,然后执行定期请求以刷新页面。如果您在 Chrome 的开发者控制台中查看网络选项卡(例如),您将看到对https://data-live.flightradar24.com/zones/fcgi/feed.js?bounds=59.09,52.64,-58.77,-47.71&faa=1&mlat=1&flarm=1&adsb=1&gnd=1&air=1&vehicles=1&estimated=1&maxage=7200&gliders=1&stats=1的请求

    响应是普通的json:

    {
      "full_count": 11879,
      "version": 4,
      "afefdca": [
        "A86AB5",
        56.4288,
        -56.0721,
        233,
        38000,
        420,
        "0000",
        "T-F5M",
        "B763",
        "N641UA",
        1473852497,
        "LHR",
        "ORD",
        "UA929",
        0,
        0,
        "UAL929",
        0
      ],
      ...
      "aff19d9": [
        "A12F78",
        56.3235,
        -49.3597,
        251,
        36000,
        436,
        "0000",
        "F-EST",
        "B752",
        "N176AA",
        1473852497,
        "DUB",
        "JFK",
        "AA291",
        0,
        0,
        "AAL291",
        0
      ],
      "stats": {
        "total": {
          "ads-b": 8521,
          "mlat": 2045,
          "faa": 598,
          "flarm": 152,
          "estimated": 464
        },
        "visible": {
          "ads-b": 0,
          "mlat": 0,
          "faa": 6,
          "flarm": 0,
          "estimated": 3
        }
      }
    }
    

    我不确定这个 API 是否受到任何保护,但我似乎可以使用 curl 毫无问题地访问它。

    更多信息:

    【讨论】:

    • 顺便问一下,有没有什么标准方法可以在“网络”选项卡中的所有请求中找到正确的 JSON 请求?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 2012-03-22
    相关资源
    最近更新 更多