使用硒在div中查找索引元素

时间:2019-04-21 22:12:27

标签: python selenium indexing web-scraping beautifulsoup

我正在抓取网页的前端,难以在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。例如,“ date” div是位置[1],因为它是其父div“ eventInfoContainer-9e539994”中的第二个元素(在img之后)。父div“ eventInfoContainer-9e539994”位于位置[1],它同样是其父div“ eventInfoContainer-54d5deb3”中的第二个元素(在“ lineupContainer”之后)。

按照这种逻辑,我不应该通过以下代码访问日期文本:(访问容器(第0个位置元素)内的第1个位置元素,其父元素为第1个位置元素吗?

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

任何帮助表示赞赏!预先谢谢你。

2 个答案:

答案 0 :(得分:2)

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

如果页面之间有规则的结构,则可以将div的html加载到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)

答案 1 :(得分:1)

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

这里

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

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

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


编辑 :(评论中的问题的答案)


这不是硒代码。

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

这可以直接使用硒来完成:

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的回答中,日期选择器将返回其他值而不是硒的预期值。