python - 使用 selenium、bs4 或 requests 从交互式图表中抓取数据

标签 python selenium web-scraping beautifulsoup

我想从这个页面的图表中抓取数据:http://188.166.44.172/match/live-stats/100941310

我尝试了 requests 和 bs4,但是没有得到任何数据,我也尝试了 selenium 也没有数据。

这是使用请求的代码:

import requests
from bs4 import BeautifulSoup

headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0'}

session = requests.Session()
r = session.get(u, timeout=30, headers=headers)    

soup = BeautifulSoup(r.content, 'html.parser')

for i in soup.find_all('rect'):
    if i.has_attr("onmouseover"):
        text = i.get('onmouseover')
        print(text)

以及使用 Selenium 的代码:

from selenium import webdriver
from bs4 import BeautifulSoup
u = "http://188.166.44.172/match/live-stats/100941310"

driver = webdriver.Chrome(executable_path=r"C:/chromedriver.exe", options=options)

driver.get(url)

soup = BeautifulSoup(driver.page_source, 'html.parser')

for i in soup.find_all('rect'):   #I also tried soup.select('*')
    if i.has_attr("onmouseover"):
        text = i.get('onmouseover')
        print(text)

有什么方法可以使用 python 从这些图表中抓取数据吗?

最佳答案

你没有得到任何返回的原因是因为所有图表都是由 JavaScript 动态生成的,例如 bs4 你不会阅读任何这个。

但是,图表的数据嵌入在 HTML 中。你可以解析它并绘制。

方法如下:

import ast
import re

import requests
import matplotlib.pyplot as plt

target_url = "http://188.166.44.172/match/live-stats/100941310"
page_source = requests.get(target_url).text

raw_attack_data = ast.literal_eval(
    re.search(r"var all_attack = (\[.*\])", page_source).group(1),
)
all_attack = [i[1] for i in raw_attack_data if isinstance(i, list)]

plt.plot(all_attack, label="attack")
plt.legend(loc="lower right")
plt.show()

这应该给你一个这样的情节:

enter image description here

正如我所说,您需要的一切都在源代码中,因此您必须尝试使用​​这些值。

来源看起来像这样:

enter image description here

内部列表的第一个值是游戏时间,第二个值是绘制在图表上的统计数据。

请注意,某些数组在 {} 中有值。这些是图表上的图标标记。您可以使用 isistance(i, list) 过滤掉它们,因为它们可以很容易地解析为 dicts,正如我在上面所示。

编辑:

是的,可以获得部门和团队信息,因为所有内容都在 HTML 中。我对最初的答案做了一些修改并得出了这个结论:

import ast
import re

import requests
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt

target_url = "http://188.166.44.172/match/live-stats/100941310"
page_source = requests.get(target_url).text


def get_match_info(html_source: str) -> list:
    return [
        i.getText(strip=True) for i
        in BeautifulSoup(html_source, "lxml").select("h1 a")
    ]


def get_stats(html_source: str, search_str: str) -> tuple:
    raw_data = ast.literal_eval(
        re.search(fr"var {search_str} = (\[.*\])", html_source).group(1),
    )
    filtered = [i[1] for i in raw_data if isinstance(i, list)]
    game_time = [i[0] for i in raw_data if isinstance(i, list)]
    return game_time, filtered


division, home, away = get_match_info(page_source)

time_, attack_home = get_stats(page_source, "dangerous_home")
_, attack_away = get_stats(page_source, "dangerous_away")

plt.suptitle(f"{division} - {home} v {away}")
plt.ylabel("Attack")
plt.xlabel("Game time")
plt.plot(time_, attack_home, color="blue", label=home)
plt.plot(time_, attack_away, color="black", label=away)
plt.legend(loc="lower right")
plt.show()

这会产生一个情节:

enter image description here

关于python - 使用 selenium、bs4 或 requests 从交互式图表中抓取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66960626/

相关文章:

python - BeautifulSoup:抓取嵌入的 href 链接列表

c++ - libcurl示例代码出现错误

python - 如何在 python 中使用套接字响应代理服务器中的 "CONNECT"方法请求?

python - 如何统计数字的总设置位数

c# - Selenium 在特定的 div 标记后单击其他 div(在 Xpath 中指定)

java - Cucumber jvm 运行所有功能后关闭浏览器

使用 rvest 进行网页抓取时出现 R 内存问题

python - Django DB在模型中存储上传的文件是否高效?

python - 在 Python 中对单个数组进行更快的双重迭代

java - Selenium 找不到 <p :calendar> day by using By. linkText()