我想从这个页面上的图表中抓取数据: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 从这些图表中抓取数据?
答案 0 :(得分:2)
您没有得到任何回报的原因是所有图表都是由 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()
这应该给你一个这样的情节:
正如我所说,您需要的一切都在源代码中,因此您必须使用这些值。
源看起来像这样:
其中内部列表的第一个值是比赛时间,第二个值是绘制在图表上的统计数据。
请注意,某些数组在 {}
中有值。这些'是图表上的那些图标标记。您可以使用 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()
这会产生一个情节: