访问工具提示 selenium 后面的元素文本 python

Accessing an element text behind a tooltip selenium python

背景:我(作为一名土壤研究人员)一直在研究一个脚本,以自动执行从荷兰大型数据库站点获取数据的过程。

站点名为 https://www.dinoloket.nl/ondergrondmodellen

每当您 select 一个位置时,您都可以获得不同模型的预期土壤堆积。 我使用的模型是regis v2.2。显示不同的岩性地层。

到目前为止,我已经能够创建 select 正确模型的脚本,输入地址并导出不同层的深度

Example of what the site gives as layer output

在图像中,它还显示了一个工具提示,该提示对于列中的每种颜色都不同。 我希望能够访问此文本,但是它一直在消失。

但是我已经阅读了其他相关问题,不同之处在于工具提示文本是可变的,具体取决于您在列中的位置。

tooltip on the site

在图像中,您可以看到工具提示 (id="columns-tooltip") 会在工具提示上的位置发生更改时显示更改消息。

有没有人知道如何访问文本“Complexe eenheid, bestaan​​de uit een afwisseling van zandige klei, midden en fijn zand, klei en veen en een weinig grof zand”

我知道这个问题含糊不清,但是一些正确方向的指示可能已经有所帮助。

谢谢

[![driver = webdriver.Chrome(PATH)
driver.get("https://dinoloket.nl\ondergrondmodellen")

#---------------- % to the website
time.sleep(1)
#---------------- % access the frame where specific buttons are located

frame = driver.find_element_by_css_selector('#block-main-content > article > div > div > div > div > div.ondergrond-modellen-tab.active > div > div > div > iframe')
driver.switch_to.frame(frame)

#----------------
time.sleep(1)

#---------------- % select model by clicking the radiobutton next to it

selectmodel= driver.find_element_by_css_selector("#mapDiv > div.esri-view-user-storage > div > dinoloket-filter-toolbar > div > div > div:nth-child(4) > p-radiobutton > div > div.ui-radiobutton-box.ui-widget.ui-state-default")
selectmodel.click()


#--------- % find the magnifying glass button and input an address

confirmdialog = driver.find_element_by_id("idSearch-button")
confirmdialog.click()

input_address= driver.find_element_by_css_selector('#search-field > div > div > input')
input_address.send_keys("Rederijweg 26, Oosterhout")


#----------------
time.sleep(1)
#---------------- % hit enter

input_address.send_keys(Keys.RETURN)

#----------------
time.sleep(2)
#---------------- %find the drillcore button that gives access to the model

drillbutton = driver.find_element_by_id("drill-button")
drillbutton.click()

#----------------
time.sleep(1)
#---------------- % click in the map element to get the model of that specific point

start = driver.find_element_by_css_selector('body > dinoloket-app > div')
start.click()][1]][1]

为了显示工具提示,您必须将鼠标悬停在某个元素上。
我们称该元素为 hoverable.
如果是这样,您的代码可以是这样的:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

wait = WebDriverWait(driver, 20)
actions = ActionChains(driver)

hoverable = driver.find_element_by_css_selector('the_element_locator')
actions.move_to_element(hoverable).perform()
tool_tip = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.mdl-columns-tooltip")))
tool_tip_text = tool_tip.text

请注意,tool_tip_text 将包含工具提示中的所有文本,在本例中包含 `Lithologie:'。

所以基本上在 Selenium-Python 中悬停,我们使用 ActionChains.

from selenium.webdriver.common.action_chains import ActionChains
action = ActionChains(driver)

您可以像下面那样使用 move_to_element 将鼠标悬停到具有工具提示的元素:-

action.move_to_element(driver.find_element_by_xpath('xpath of element which has tool tip')).perform()
tool_tip_text = driver.find_element_by_xpath("//div[@id='columns-tooltip']").text
print(tool_tip_text)

现在,可能会出现一种情况,通过阅读您的 post,我们似乎可以提取不止一个工具提示,如果是这样,您可以使用 find_elements 而不是 find_element,但如果碰巧是,请确保传递一个公共定位器。

作为替代方案,您是否知道您的页面有一个 API。您可以使用它一次性收集所有元素所需的所有数据,而无需靠近浏览器。它会明显更快更稳定。

试试这个代码:

import requests

url = 'https://www.dinoloket.nl/javascriptmodelviewer-web/rest/models/columns/descripted'

postData = {
    "language":"nl",
    "modelType":"RGS",
    "model":"REGIS",
    "depthReference":"NAP",
    "version":"v02r2",
    "dinoId":"B32F0034",
    "topDepth":"null",
    "bottomDepth":"null"
    }

response = requests.post(url=url, json=postData)
json_response = response.json()


for columns in json_response['columns']:
    for values in columns['profileMetadata']:
        for layer in values['layerInfos']:
            if layer['code'] == 'LITHOLOGY':
                print ("type: " , columns['columnType'])
                print ('upper: ', values['upper'])
                print ('lower' , values['lower'])
                print ('Code: ' , layer['code'])
                print ('value: ', layer['value'])
                print ('\n###############\n') # seperator

postData 中您可以看到 "model":"REGIS" - 您说您正在使用。

"dinoId":"B32F0034" 似乎与标识符有关:

当我 运行 该代码时,我得到以下输出 - 这似乎是该页面上的每个“岩石学”工具提示:

type:  HYDROGEOLOGY
upper:  344
lower 386
Code:  LITHOLOGY
value:  Zandige eenheid, hoofdzakelijk bestaande uit midden en grof zand, met weinig zandige klei, 
fijn zand en grind en een spoor klei en veen

###############

type:  HYDROGEOLOGY
upper:  21
lower 138
Code:  LITHOLOGY
value:  Zandige eenheid, hoofdzakelijk bestaande uit midden en fijn zand, weinig zandige klei en grof zand en een spoor klei, veen en grind

###############

type:  HYDROGEOLOGY
upper:  140
lower 197
Code:  LITHOLOGY
value:  Kleiige eenheid, hoofdzakelijk bestaande uit zandige klei en klei, weinig fijn en midden zand en een spoor veen en grof zand

###############

type:  HYDROGEOLOGY
upper:  199
lower 266
Code:  LITHOLOGY
value:  Zandige eenheid, hoofdzakelijk bestaande uit midden, grof en fijn zand, weinig kleiig zand 
en een spoor klei en grind

###############

type:  HYDROGEOLOGY
upper:  268
lower 335
Code:  LITHOLOGY
value:  Zandige eenheid, hoofdzakelijk bestaande uit grof en midden zand, weinig zandige klei, fijn zand en grind en een spoor klei

###############

type:  HYDROGEOLOGY
upper:  337
lower 342
Code:  LITHOLOGY
value:  Kleiige eenheid, hoofdzakelijk bestaande uit zandige klei weinig klei, fijn, midden en grof zand, een spoor grind en een kans op stenen, keien en blokken

###############

我不知道 lowerupper 是否对您有用 - 它们只是作为提取的示例数据。

根据您需要的其他信息,您可以在网络选项卡上的开发工具中探索从站点返回的 JSON 数据结构。当您使用您的网站并找到名为 descripted 的项目进行浏览时,在后台打开此选项卡



* * * * * **更新** * * * * * *

将 API 链接在一起以允许在地址处进行演练。

更新脚本开头的地址,它将输出其余部分。交给你来获得你想要的输出格式:

import requests
import urllib.parse

#Enter the address to drill - this is all that's needed
address = urllib.parse.quote("Rederijweg 26, Oosterhout")


#user the search suggested to get the ID for the address 
suggest_response = requests.get('https://geodata.nationaalgeoregister.nl/locatieserver/v3/suggest?q='+address)
suggest_json = suggest_response.json()
address_ID = suggest_json['response']['docs'][0]['id']
#address id  is something like" adr-21ceef9f7c9e361352969a3bcab636e6"


#use the address ID to get the coordinates:
lookup_response = requests.get("https://geodata.nationaalgeoregister.nl/locatieserver/v3/lookup?fl=centroide_rd,type&id=" + address_ID)
lookup_json = lookup_response.json()
coords_string =lookup_json['response']['docs'][0]['centroide_rd']
#coords come in like: POINT(117454.426 408494.3)
# prcess this into 2 values
coords_string= str.replace(coords_string, "POINT(", "")
coords_string= str.replace(coords_string, ")", "")
coords_array = str.split(coords_string, " ")


#use those coordinates to drill
url = "https://www.dinoloket.nl/javascriptmodelviewer-web/rest/models/columns/virtual"
postData = {
  "language": "nl",
  "modelType": "RGS",
  "model": "REGIS",
  "depthReference": "MV",
  "version": "v02r2",
  "resolution": "100",
  "ycoordinate":float(coords_array[1]),
  "xcoordinate":float(coords_array[0])
}

response = requests.post(url=url, json=postData)
json_response = response.json()

#process the drill results
for columns in json_response['columns']:
    for meta in columns['profileMetadata']:
        for layer in meta['layerInfos']:
            if layer['code'] == 'LITHOLOGY':
                print ("type: " , columns['columnType'])
                print ('upper: ', meta['upper'])
                print ('lower' , meta['lower'])
                print ('Code: ' , layer['code'])
                print ('value: ', layer['value'])
                print ('\n###############\n') # seperator

对我来说,只输出TOP 3(节省一些粘贴-space):

type:  HYDROGEOLOGY
upper:  20
lower 21
Code:  LITHOLOGY
value:  Complexe eenheid, bestaande uit een afwisseling van zandige klei, midden en fijn zand, klei en veen en een weinig grof zand

###############

type:  HYDROGEOLOGY
upper:  21
lower 22
Code:  LITHOLOGY
value:  Zandige eenheid, hoofdzakelijk bestaande uit midden en fijn zand, met weinig zandige klei en grof zand en een spoor klei, veen en grind

###############

type:  HYDROGEOLOGY
upper:  22
lower 23
Code:  LITHOLOGY
value:  Zandige eenheid, hoofdzakelijk bestaande uit midden en fijn zand, met weinig zandige klei en grof zand en een spoor klei, veen en grind

不知道这些描述在整个网站上有多独特 - 但它匹配: