开发者问题收集

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

2021-08-12
1114

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

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

每当您选择一个位置时,您都可以获得不同模型的预期土壤积聚情况。 我使用的模型是 regis v2.2。显示不同的岩性构造。

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

站点提供的层输出示例

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

我读过其他相关问题,但是不同之处在于工具提示文本会根据您在列中的位置而变化。

网站上的工具提示

在图像中,您可以看到工具提示 (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]
3个回答

作为替代方案,您是否知道您的页面有一个 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" 似乎与标识符有关:

target identifer

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

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 的项目进行浏览

devtools



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

将 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(节省一些粘贴空间):

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

不知道这些描述在整个网站上有多独特 - 但它匹配: 在此处输入图片描述

RichEdwards
2021-08-12

为了显示工具提示,您必须将鼠标悬停在某些元素上。
我们将该元素称为 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:”。

Prophet
2021-08-12

因此,基本上对于在 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)

现在,可能存在一种情况,通过阅读您的帖子,似乎我们可能有多个工具提示需要提取,如果是这样,您可以使用 find_elements 而不是 find_element ,但如果碰巧是这样,请确保传递一个通用定位器。

cruisepandey
2021-08-12