访问工具提示 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, bestaande 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
###############
我不知道 lower
和 upper
是否对您有用 - 它们只是作为提取的示例数据。
根据您需要的其他信息,您可以在网络选项卡上的开发工具中探索从站点返回的 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
不知道这些描述在整个网站上有多独特 - 但它匹配:
背景:我(作为一名土壤研究人员)一直在研究一个脚本,以自动执行从荷兰大型数据库站点获取数据的过程。
站点名为 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, bestaande 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
###############
我不知道 lower
和 upper
是否对您有用 - 它们只是作为提取的示例数据。
根据您需要的其他信息,您可以在网络选项卡上的开发工具中探索从站点返回的 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
不知道这些描述在整个网站上有多独特 - 但它匹配: