【问题标题】:Using Selenium to find indexed element within a div使用 Selenium 在 div 中查找索引元素
【发布时间】:2019-09-11 05:20:40
【问题描述】:

我正在抓取网页的前端,并且难以在 div 中获取 div 的 HMTL 文本。

基本上,我是在模拟点击——页面上列出的每个事件都有一个。从那里,我想抓取事件的日期和时间,以及事件的位置。

这是我试图抓取的页面之一的示例:

https://www.bandsintown.com/e/1013664851-los-grandes-de-la-banda-at-aura-nightclub?came_from=257&utm_medium=web&utm_source=home&utm_campaign=event

<div class="eventInfoContainer-54d5deb3">
    <div class="lineupContainer-570750d2"> 
    <div class="eventInfoContainer-9e539994">
        <img src="assets.bandsintown.com/images.clock.svg">
        <div>Sunday, April 21st, 2019</div> <!––***––> 
        <div class="eventInfoContainer-50768f6d">5:00PM</div><!––***––> 
     </div> 
<div class="eventInfoContainer-1a68a0e1">
    <img src="assets.bandsintown.com/images.clock.svg">
    <div class="eventInfoContainer-2d9f07df">
        <div>Aura Nightclub</div> <!––***––> 
        <div>283 1st St., San Jose, CA 95113</div> <!––***––> 
</div>

我已用星号标记了要提取的元素 - 日期、时间、地点和地址。这是我的代码:

base_url = 'https://www.bandsintown.com/?came_from=257&page='
events = []
eventContainerBucket = []
for i in range(1, 2):
    driver.get(base_url + str(i))

# get events links
event_list = driver.find_elements_by_css_selector('div[class^=eventList-] a[class^=event-]')
# collect href attribute of events in even_list
events.extend(list(event.get_attribute("href") for event in event_list))



# iterate through all events and open them.
for event in events:
    driver.get(event)
    uniqueEventContainer = driver.find_elements_by_css_selector('div[class^=eventInfoContainer-]')[0]
   
    print "Event information: "+ uniqueEventContainer.text

打印出来:

Event information: Sunday, April 21st, 2019
3:00 PM
San Francisco Brewing Co.
3150 Polk St, Sf, CA 94109
View All The Fourth Son Tour Dates

我的问题是我无法单独访问嵌套的 eventInfoContainer div。例如,“日期”div 是位置 [1],因为它是其父 div“eventInfoContainer-9e539994”中的第二个元素(在 img 之后)。父 div "eventInfoContainer-9e539994" 位于位置 [1] 是否也是其父 div "eventInfoContainer-54d5deb3" 中的第二个元素(在 "lineupContainer" 之后。

按照这种逻辑,我是否应该能够通过以下代码访问日期文本:(访问第一个位置元素,它的父元素是容器内的第一个位置元素(第 0 个位置元素)?

for event in events:
    driver.get(event)
    uniqueEventContainer = driver.find_elements_by_css_selector('div[class^=eventInfoContainer-]')[0][1][1]

我收到以下错误:

TypeError: 'WebElement' object does not support indexing

【问题讨论】:

    标签: python selenium indexing web-scraping beautifulsoup


    【解决方案1】:

    当您对 webElements 列表(这是 find_elements_by_css_selector('div[class^=eventInfoContainer-]') 返回的内容)进行索引时,您将获得一个 webElement,您无法进一步对其进行索引。您可以拆分 webElement 的文本以生成列表以供进一步索引。

    如果页面之间存在规则结构,您可以将 html for div 加载到 BeautifulSoup 中。示例网址:

    from selenium import webdriver
    from bs4 import BeautifulSoup as bs
    
    d = webdriver.Chrome()
    d.get('https://www.bandsintown.com/e/1013664851-los-grandes-de-la-banda-at-aura-nightclub?came_from=257&utm_medium=web&utm_source=home&utm_campaign=event')
    soup = bs(d.find_element_by_css_selector('[class^=eventInfoContainer-]').get_attribute('outerHTML'), 'lxml')
    date = soup.select_one('img + div').text
    time = soup.select_one('img + div + div').text
    venue = soup.select_one('[class^=eventInfoContainer-]:nth-of-type(3) div > div').text
    address = soup.select_one('[class^=eventInfoContainer-]:nth-of-type(3) div + div').text
    
    print(date, time, venue, address)
    

    如果换行符一致:

    containers = d.find_elements_by_css_selector('div[class^=eventInfoContainer-]')
    array = containers[0].text.split('\n')
    date = array[3]
    time = array[4]
    venue = array[5]
    address = array[6]
    print(date, time, venue, address)
    

    带索引和拆分:

    from selenium import webdriver
    from bs4 import BeautifulSoup as bs
    
    d = webdriver.Chrome()
    d.get('https://www.bandsintown.com/e/1013664851-los-grandes-de-la-banda-at-aura-nightclub?came_from=257&utm_medium=web&utm_source=home&utm_campaign=event')
    containers = d.find_elements_by_css_selector('div[class^=eventInfoContainer-]')
    date_time = containers[1].text.split('\n')
    i_date = date_time[0]
    i_time = date_time[1]
    venue_address = containers[3].text.split('\n')
    venue = venue_address[0]
    address = venue_address[1]
    print(i_date, i_time, venue, address)
    

    【讨论】:

      【解决方案2】:

      正如错误提示的那样,webelements 没有索引。您感到困惑的是列表。

      这里

      driver.find_elements_by_css_selector('div[class^=eventInfoContainer-]')
      

      此代码返回一个 web 元素列表。这就是为什么您可以使用列表的索引访问 web 元素的原因。但是该元素没有对另一个 web 元素的索引。您没有得到列表列表。

      这就是为什么 driver.find_elements_by_css_selector('div[class^=eventInfoContainer-]')[0] 有效。但是driver.find_elements_by_css_selector('div[class^=eventInfoContainer-][0][1]') 没有。


      编辑:(在评论中回答问题)


      这不是 slenium 代码。

      QHarr 在答案中发布的代码使用BeautifulSoup。它是一个用于解析 HTML 和 XML 文档的 python 包。
      BeautifulSoup 有一个 .select() 方法,它使用 CSS 选择器对已解析的文档并返回所有匹配的元素。
      还有一个叫做select_one()的方法,它只找到第一个匹配选择器的标签。

      在代码中,

      time = soup.select_one('img + div + div').text 
      venue = soup.select_one('[class^=eventInfoContainer-]:nth-of-type(3) div > div').tex
      

      它获取给定 CSS 选择器找到的第一个元素并返回标签内的文本。第一行找到img 标签,然后找到直接兄弟div 标签,然后再次找到前一个div 标签的兄弟dev 标签。 在第二行中,它找到类以eventInfoContainer- 开头的第三个兄弟标签,然后找到子标签div 并找到该div 的子标签。

      查看CSS selectors

      这可以直接使用 selenium 完成:

      date = driver.find_element_by_css_selector("img[class^='eventInfoContainer-'][src$='clock.svg'] + div")
      time = driver.find_element_by_css_selector("img[class^='eventInfoContainer-'] + div + div")
      venue = driver.find_element_by_css_selector("img[class^='eventInfoContainer-'][src$='pin.svg'] + div > div")
      address = driver.find_element_by_css_selector("img[class^='eventInfoContainer-'][src$='pin.svg'] + div > div:nth-of-type(2)")
      

      我使用了不同的 CSS 选择器,但它仍然选择相同的元素。
      我不确定BeautifulSoup,但在 QHarr 的回答中,日期选择器将返回其他值而不是硒的预期值。

      【讨论】:

      • 感谢您的帮助。你能解释一下这段代码是如何工作的吗?仍然不了解 Selenium 中的这种方法。 time = soup.select_one('img + div + div').text 场地 = soup.select_one('[class^=eventInfoContainer-]:nth-of-type(3) div > div').text
      • @DiamondJoe12 根据您的问题更新了答案。
      猜你喜欢
      • 1970-01-01
      • 2017-09-12
      • 1970-01-01
      • 2019-06-04
      • 2023-04-10
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 2020-11-22
      相关资源
      最近更新 更多