无法使用 Selenium(无头)检索 Javascript 图表后面的 data/array

Unable to retrieve the data/array behind Javascript chart using Selenium (headless)

我正在尝试通过网络抓取本网站上的历史 'Market Value Dvelopment' 图表:

https://www.transfermarkt.com/neymar/marktwertverlauf/spieler/68290

在得知它是 javascript 之后,我开始学习使用网络驱动程序 (Selenium)、无头浏览器和 Chrome/Chromium 进行网页抓取 JS。检查页面后,我发现我可能正在寻找的 ID 是 id_= 'yw0',它似乎包含图表:

鉴于此,这是我的代码:

import selenium as se
from selenium import webdriver

options = se.webdriver.ChromeOptions()
options.add_argument('headless')

driver = se.webdriver.Chrome(executable_path='/Applications/Utilities/chromedriver', chrome_options=options)
driver.get('https://www.transfermarkt.com/neymar/marktwertverlauf/spieler/68290')
element = driver.find_element_by_id(id_='yw0')

print(element)

当我 运行 它输出这个:

<selenium.webdriver.remote.webelement.WebElement (session="bd8e42834fcdd92383ce2ed13c7943c0", element="8df128aa-d242-40a0-9306-f523136bfe57")>

element后的代码更改为

value = element.text

print(value)

我得到:

Current Market Value : 180,00 Mill. €
2010
2012
2014
2016
2018
50,0
100,0
150,0
200,0

这不是数据,而是图表间隔的 x 和 y 值。

我尝试了图表的不同 id 标签,看看我是否只是识别了错误的容器(例如 highcharts-0)。但是我无法找到图表的实际数据值。

奇怪的是,在我 运行 我的代码之后图表发生了一些变化。图表 'gets wider' 和 运行s 关闭图表的指定区域。它看起来像这样:

我想知道为了抓取显示在图表上的数据点,我可以并且需要更改代码中的哪些内容。

您可以从 javascript 中提取它并进行一些字符串操作。您可以从下面获得字典列表。不需要硒。

import requests, re, ast

r = requests.get('https://www.transfermarkt.com/neymar/marktwertverlauf/spieler/68290', headers = {'User-Agent':'Mozilla/5.0'})
p = re.compile(r"'data':(.*)}\],")
s = p.findall(r.text)[0]
s = s.encode().decode('unicode_escape')
data = ast.literal_eval(s)

查看第一项:


正则表达式:


tl;dr;

在加载时使用浏览器时 jQuery 从 script 标签中提取图表信息,从而生成您所看到的内容。正则表达式提取相同的信息,即图表的相关系列信息,jQuery 来源系列。


硒:

这当然有改进的余地,但它展示了一般原则。当您将鼠标悬停在图表上的每个数据点上时,会从脚本标签中检索这些值以更新工具提示。检索到的值与图表点的 x,y 相关联。因此,您无法从查看工具提示信息的位置读取信息。相反,您可以单击每个数据点并从工具提示元素中获取更新的信息。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from bs4 import BeautifulSoup as bs
from selenium.webdriver.chrome.options import Options
import time

options = Options()
options.add_argument("--start-maximized")

url = 'https://www.transfermarkt.com/neymar/marktwertverlauf/spieler/68290'
d = webdriver.Chrome(options = options)
d.get(url)
WebDriverWait(d, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".as-oil__btn-optin"))).click()
markers = d.find_elements_by_css_selector('.highcharts-markers image')
time.sleep(1)
for marker in markers:
    ActionChains(d).click_and_hold(marker).perform()
    text = d.find_element_by_css_selector('div.highcharts-tooltip').text
    while True:
        if len(text) == 0:
            ActionChains(d).click_and_hold(marker).perform()
        else:
            break
    print(text)