首页 > 解决方案 > 无法使用 Selenium(无头)检索 Javascript 图表后面的数据/数组

问题描述

我正在尝试在此网站上抓取历史“市场价值发展”图表:

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

在得知它是 javascript 之后,我开始学习使用 webdrivers (Selenium)、无头浏览器和 Chrome/Chromium 来抓取 JS。检查页面后,我发现我可能正在寻找的 IDid_= '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)。但我无法找到图表的实际数据值。

奇怪的是,在我运行我的代码后,图表会发生一些变化。图表“变宽”并超出图表的指定区域。它看起来像这样:

在此处输入图像描述

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

标签: javascriptpythonseleniumweb-scrapingraphael

解决方案


您可以从 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;博士;

在加载时使用浏览器时,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)

推荐阅读