SeleniumXPATH一直在循环中获取错误的标记元素



我目前正在网上抓取我的大学网页以下载单元内容。我已经找到了如何收集每个单元的名称/链接,现在正试图找到如何整理单元中每个单独模块的名称/连接。

模块页面上HTML的大致描述。

<ul id="content_listContainer" class="contentList">
<li id="" class="clearfix liItem read">
<img></img>
<div class="item clearfix">
<h3>
<a href="Link To Module">
<span>Name of Module</span>
</a>
</h3>
</div>
</li>
<li id="" class="clearfix liItem read">
<img></img>
<div class="item clearfix">
<h3>
<a href="Link To Module">
<span>Name of Module</span>
</a>
</h3>
</div>
</li>
</ul>

因此,我试图获取li/div/h3中<a>标记的href属性内的链接,以及<a>标记内span内模块的名称。以下是相关的代码片段。

modules = []

driver.get(unit_url)
module_ul = driver.find_element_by_xpath("//ul[@id='content_listContainer']")    #Grab the ul list
li_items = module_ul.find_elements_by_xpath("//li[@class='clearfix liItem read']")  #Grab each li item
for item in li_items[1:]:              #Skips first li tag as that is the Overview, not a module
module_url = item.find_element_by_xpath("//div[@class='item clearfix']/h3/a").get_attribute('href') 
#These are not moving on from the first module for some reason...
module_name = item.find_element_by_xpath("//div[@class='item clearfix']/h3/a/span").text
module = {
"name": module_name,
"url": module_url
}
modules.append(module)

问题:

编辑

不幸的是,我尝试过@sushii和@QHarr解决方案,但没有成功。我应该指出,在for循环中获取module_name和module_url的行在每个loop中都返回相同的第一个模块数据。我用另一个单元测试了它,其中第一对<li>标签是非模块的(介绍(,应该返回,但它仍然只返回相同的模块1。

/edit

编辑2

这是我试图抓取的html的链接。这不是整个页面,因为那样会太大。

<html><body><div></div><div></div><div></div><div>这是链接中的DIV</div><div></div><div></div></body></html>

我已经验证了li_items肯定包含我需要的<li>标记,所以其他HTML应该不重要(我认为(。

如果向下滚动约四分之一,则我需要的<li>标记为粗体,并且我需要抓取的信息为下划线。

/编辑2

在for循环中获取module_name和module_url的行只获取第一个模块的信息。

我已经通过调试验证了li_items确实包含了所有的li项,而不仅仅是获取第一个。我是Selenium的新手,所以我的想法是我提供的xpath有问题,但它应该只抓取项可迭代对象中的标记。所以我很困惑为什么它一直在抓取第一个李的信息。

应答编辑

使用@Sariq Shaikh的答案,我解决了这个问题。最初,他使用元素索引[]来迭代<li>标记的技术不起作用,但在更改用于module_url和module_name的XPATH以包括<ul>标记,然后使用<li>标记的索引后,解决了我的问题。

然而,我仍然不明白为什么最初的方法不起作用。这是修改后的代码。

module_ul = driver.find_element_by_xpath("//ul[@id='content_listContainer']")
ctr = 1
for _ in module_ul.find_elements_by_tag_name('li'):

try:
module_url = driver.find_element_by_xpath('//ul[@id="content_listContainer"]/li[' + str(ctr) + ']/div/h3/a').get_attribute('href') #These are not moving on from the first module for some reason...
module_name = driver.find_element_by_xpath('//ul[@id="content_listContainer"]/li[' + str(ctr) + ']/div/h3/a/span').text

except SelException.NoSuchElementException:
print("NoSuchElementExceptionn")
ctr += 1
continue

要迭代地获取所有列表项,可以使用xpath和index,如下所示。

(//div[@class='item clearfix'])[1] #first li item index starts from 1 not 0
(//div[@class='item clearfix'])[2] #second li item
(//div[@class='item clearfix'])[3] #third li item
(//div[@class='item clearfix'])[4] #fourth li item

在使用索引获取每个li项之后,您可以根据它们在xpath中的存在来访问其子元素,如下所示。

(//div[@class='item clearfix'])[1]/h3/a #first li's h3/a tag

考虑到这一点,您可以更新您的代码,如下所示,使用一个简单的计数器来获取基于索引的列表元素。

modules = []
module_ul = driver.find_element_by_xpath("//ul[@id='content_listContainer']")    #Grab the ul list
li_items = module_ul.find_elements_by_xpath("//li[@class='clearfix liItem read']")  #Grab each li item
counter = 1 #use counter to iterate over all the li items based on index
for item in li_items:
#append counter values as index for list items in xpath
module_url = item.find_element_by_xpath("(//div[@class='item clearfix'])["+str(counter)+"]/h3/a").get_attribute('href') 
module_name = item.find_element_by_xpath("(//div[@class='item clearfix'])["+str(counter)+"]/h3/a/span").text
module = {
"name": module_name,
"url": module_url
}
modules.append(module)
counter= counter + 1

#remove the first item from the list as its not required
modules.pop(0)
print(modules)

使用BeautifulSoup实际上非常简单。以下是如何使用BeautifulSoup:

from bs4 import BeautifulSoup
html = """
<ul id="content_listContainer" class="contentList">
<li id="" class="clearfix liItem read">
<img></img>
<div class="item clearfix">
<h3>
<a href="Link To Module">
<span>Name of Module</span>
</a>
</h3>
</div>
</li>
<li id="" class="clearfix liItem read">
<img></img>
<div class="item clearfix">
<h3>
<a href="Link To Module">
<span>Name of Module</span>
</a>
</h3>
</div>
</li>
</ul>
"""
soup = BeautifulSoup(html,'html.parser')
lis = soup.find_all('li',class_ = 'clearfix liItem read')
for li in lis:
print(li.div.h3.a['href'])

输出:

Link To Module
Link To Module

希望这能有所帮助!

编辑:

由于ur网站是使用javascript动态加载的,因此u shd首先在selenium中打开url,获取网站的html代码并关闭浏览器。以下是你的操作方法:

from selenium import webdriver
driver = webdriver.Chrome()
driver.get(url)
html = driver.page_source

然后U可以使用BeautifulSoup解析这个html。希望这能有所帮助!

您应该能够使用css选择器并避免循环。

import pandas as pd
results = pd.DataFrame(zip([i.text for i in driver.find_elements_by_css_selector('#content_listContainer span')]
, [i.get_attribute('href') for i in driver.find_elements_by_css_selector.('#content_listContainer a')])
, columns = ['Name', 'Link'])
print(results)

我刚刚遇到了一个非常类似的问题,虽然我不确定为什么,但我想我已经找到了一个解决方案:

如果更换

module_url = item.find_element_by_xpath("//div[@class='item clearfix']/h3/a").get_attribute('href')

带有

module_url = item.find_element_by_xpath("./div[@class='item clearfix']/h3/a").get_attribute('href')

在中,在xpath开始时用./替换//(并在module_namexpath中进行相同的替换(,那么我认为它应该可以工作。我在你提供的html上尝试过,它似乎有效。再说一次,我真的不确定它为什么有效,我试过查看XPath文档,但老实说,这对我来说都是希腊语。

相关内容

  • 没有找到相关文章

最新更新