Python Selenium驱动程序:通过xpath查找元素;如何解析2级表(即表中的表)
我问了一个问题来说明这一点,但由于这是一个具体的不同问题,所以我将其分开,但如果这不是正确的地方,请告诉我 我有这个剧本:Python Selenium驱动程序:通过xpath查找元素;如何解析2级表(即表中的表),python,selenium,beautifulsoup,Python,Selenium,Beautifulsoup,我问了一个问题来说明这一点,但由于这是一个具体的不同问题,所以我将其分开,但如果这不是正确的地方,请告诉我 我有这个剧本: from selenium import webdriver from bs4 import BeautifulSoup import os from selenium.webdriver.support.ui import Select from selenium.webdriver.common.by import By from selenium.webdriver.
from selenium import webdriver
from bs4 import BeautifulSoup
import os
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
options = Options()
options.binary_location=r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options,executable_path='/mnt/c/Users/kela/Desktop/selenium/chromedriver.exe')
#get the url
driver.get('http://147.8.185.62/services/NutriChem-2.0/')
#find the food name
element = driver.find_element_by_id("input_food_name")
element.send_keys("22663")
#click food-disease association
element = Select(driver.find_element_by_css_selector('[name=food_search_section]'))
element.select_by_value('food_disease')
#click submit and click plant-disease associations
driver.find_element_by_css_selector('[value="Submit"]').click()
driver.switch_to.frame(driver.find_element_by_css_selector('frame'))
driver.find_element_by_css_selector('[onclick*="plant-disease"]').click()
#to click into each drop down table rows
driver.switch_to_default_content()
driver.switch_to.frame(driver.find_element_by_name('mainFrame'))
driver.switch_to.frame(driver.find_element_by_name('ListWeb'))
这让我进入了我想要浏览的页面:
下一步,对于每个灰色框,我想拉出(1)PMID,(2)植物,(3)方向(通过图像是up_arrow.png还是down_arrow.png表示,所以只需打印图像名称就可以了)和(4)疾病
从我的上一个问题中可以看出,我对selenium非常陌生,并且认为一旦我进入这一阶段,我将通过表格行循环并使用beautifulSoup打印这些行。我的问题的简短版本是,我就是不能让它工作
我尝试过的事情:
尝试1:
rows = driver.find_elements_by_xpath("//table[@class='Level1Table']//tr[contains(@name,'hList')]")
test_row = rows[0]
print(test_row.text)
上述代码将打印“石榴骨性关节炎3”;但是,我无法解决如何在此循环(我只得到空数据)
尝试2:
然后我试着按行循环遍历每个r,但这仍然只能得到级别1的数据。(即,仅打印多行尝试1)
尝试3:
rows = Select(driver.find_elements_by_xpath("//table[@class='Level2Table']//tr[contains(@name,'hList')]"))
print(rows)
在上面,我想知道为什么我不能运行与尝试1相同的操作,而是通过级别2表而不是级别1循环。此输出为空。我不知道为什么这不起作用;我可以通过查看页面看到level2table在那里
尝试4:
这是我最初考虑的方式,但它不起作用:
for row in rows.findAll('tr'):
food_source = row.find_all('td')[1].text
pmid = row.find_all('td')[0].text
disease = row.find_all('td')[3].text
#haven't figured out how to get the association direction yet
print(food_source + '\t' + pmid + '\t' + disease + '\t' + association)
这是我的第一个selenium脚本,所以在这一点上,我只是超出了我的深度。有人能告诉我如何在1级表格中循环2级表格,并提取所需信息(参考、植物、方向和疾病)
编辑1:根据盖伊下面的建议,这是完整的脚本:
from selenium import webdriver
from bs4 import BeautifulSoup
import os
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import pandas as pd
options = Options()
options.binary_location=r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options,executable_path='/mnt/c/Users/kela/Desktop/selenium/chromedriver.exe')
#get the url
driver.get('http://147.8.185.62/services/NutriChem-2.0/')
#find the food name
element = driver.find_element_by_id("input_food_name")
element.send_keys("22663")
#click food-disease association
element = Select(driver.find_element_by_css_selector('[name=food_search_section]'))
element.select_by_value('food_disease')
#click submit and click plant-disease associations
driver.find_element_by_css_selector('[value="Submit"]').click()
driver.switch_to.frame(driver.find_element_by_css_selector('frame'))
driver.find_element_by_css_selector('[onclick*="plant-disease"]').click()
#to click into each drop down table rows
driver.switch_to_default_content()
driver.switch_to.frame(driver.find_element_by_name('mainFrame'))
#driver.switch_to.frame(driver.find_element_by_name('ListWeb'))
#rows = driver.find_elements_by_xpath("//table[@class='Level1Table']//tr[contains(@name,'hList')]")
#test_row = rows[0]
driver.switch_to.frame('ListWeb') # no need for find_element, name or id are sufficient
rows = driver.find_elements_by_css_selector('[id^="ListTAXID"] [name^="Item"]')
for row in rows:
row_data = row.find_elements_by_xpath('.//td')
pmid = row_data[0].text
plant = row_data[1].text
direction = row_data[2].get_attribute('src')
disease = row_data[3].text
print(str(pmid) + '\t' + str(plant) + '\t' + str(direction) + '\t' + str(disease))
这导致了这个输出:
None
None
None
None
None
None
None
None
None
None
None
None
内部表格不是标题行的一部分(带有
'Pomegranate Osteoartritis 3'
文本),而是在不可见的兄弟行中
这些行具有以有助于识别它们的ListTAXID
开头的id
属性,并且您要查找的数据位于以Item
开头的name
属性的子元素中
仅当表格打开时,文本才可用。您可以在收集数据之前单击所有标题行,或者使用get_属性('innerText')
而不是text
,即使表仍然关闭,它也会获取数据
driver.switch_to.frame('ListWeb') # no need for find_element, name or id are sufficient
rows = driver.find_elements_by_css_selector('[id^="ListTAXID"] [name^="Item"]')
for row in rows:
row_data = row.find_elements_by_xpath('.//td')
pmid = row_data[0].get_attribute('innerText')
plant = row_data[1].get_attribute('innerText')
direction = 'up_arrow' if 'up_arrow' in row_data[2].find_element_by_xpath('.//img').get_attribute('src') else 'down_arrow'
disease = row_data[3].get_attribute('innerText')
作为旁注,您应该最大化您的窗口
驱动程序。一旦进入要刮取的页面,请最大化\u window()
import pandas as pd
raw = driver.page_source
soup = bs(raw,'lxml')
df = pd.read_html(soup.prettify(),attrs={'class':'Level2Table'})
我认为熊猫将是这里的正确选择。
请共享您希望从中提取数据的表的HTML。谢谢,我可以检查一下这是经过测试的还是未经测试的,因为我得到了:AttributeError:“WebElement”对象没有“find_all”属性?@Slowat_Kela我从您的代码中获取了它。您可以使用
行。改为使用xpath('.//td')
查找元素。请参阅更新的答案。谢谢,我刚刚编辑了我的上述问题,以便添加到您的代码中,如果您可以看到我的问题,输出是什么样的?
# to click into each drop down table rows
driver.switch_to.default_content()
driver.switch_to.frame(driver.find_element_by_name('mainFrame'))
driver.switch_to.frame(driver.find_element_by_name('ListWeb'))
page = BeautifulSoup(driver.page_source, "html.parser")
items = page.select(".Level2Table tr[name^='Item']")
for item in items:
item_data = item.select("td")
pmid = item_data[0].text
plant = item_data[1].text
direction = "up" if "up_arrow.png" in item_data[2].select_one("img").attrs["src"] else "down"
disease = item_data[3].text
print(f"pmid: {pmid}, plant: {plant}, direction: {direction}, disease: {disease}")