Selenium Python选择器返回太多值

时间:2017-07-06 17:55:20

标签: python selenium web-scraping css-selectors

想知道是否有人可以给我一些使用Selenium和Python进行网页编写的建议。

我需要在页面上获取具有特定类的元素数量,并且我使用它

driver=webdriver.PhantomJS()
driver.get('https://www.somerandomsite.com/1')
number_of_elements = len(driver.find_elements_by_class_name('some_class'))

每次都能获得正确数量的元素。

但现在我想定义一个函数,以便它可以抓取多个网页 - 比如说https://www.somerandomsite.com/1https://www.somerandomsite.com/10

所以我做了

driver=webdriver.PhantomJS()
def my_func(start,end)
    while start <= end:
        driver.get('https://www.somerandomsite.com/'+str(start))
        number_of_elements = len(driver.find_elements_by_class_name('some_class'))
        start += 1

理论上,这应该移到下一页,并检索我想要在该页面中的类数。但是,它适用于第一页,但后续页面会产生许多元素,这些元素要么等于上一页的元素数加上当前页的元素数,要么总和减1.如果我使用xpath而不是类名选择器我得到完全相同的结果。

此外,如果我尝试访问该较长列表中的任何元素,则会抛出错误,因为只有该页面上的值实际存在。因此,如果它上面的元素甚至不存在,我也不知道如何获得更长的列表。 (例如,如果第一页上有8个元素,第二页上有5个元素,当它到达第二页时,它会说有12或13个元素。如果我访问元素1-5,它们都返回值,但是试图调用第六个或更高的元素将导致NoSuchElementException。)

任何人都知道为什么会发生这种情况?

编辑:我已经把它缩小了一点,希望这会有所帮助。对不起,我在最初的问题上离开了。

driver=webdriver.PhantomJS()
def my_func(start,end)
    while start <= end:
        driver.get('https://www.somerandomsite.com/'+str(start))
        number_of_elements = len(driver.find_elements_by_class_name('some_class'))
        start += 1

所以上面的代码实际上是有效的。但是,当我导航到另一个也包含&#39; some_class&#39;元素的页面,然后继续循环时,它会将前一页面中的元素数量添加到当前页面。

所以我的代码是这样的:

driver=webdriver.PhantomJS()
def my_func(start,end)
    while start <= end:
        driver.get('https://www.somerandomsite.com/'+str(start))
        number_of_elements = len(driver.find_elements_by_class_name('some_class'))
        print(number_of_elements)
        driver.get('https://www.somerandomsite.com/otherpage')
        start += 1

my_func(1,2)

所以,让我们说https://www.somerandomsite.com/1有8个类的元素&#39; some_class&#39;,https://www.somerandomsite.com/otherpage有7个元素的类&#39; some_class&#39;和{ {3}}有10个类的元素&some; class_class&#39;。

当我运行上面的代码时,它会打印8,然后是17.如果我没有导航到另一页,那就运行

driver=webdriver.PhantomJS()
def my_func(start,end)
    while start <= end:
        driver.get('https://www.somerandomsite.com/'+str(start))
        number_of_elements = len(driver.find_elements_by_class_name('some_class'))
        start += 1

所以上面的代码实际上是有效的。但是,当我导航到另一个也包含&#39; some_class&#39;元素的页面,然后继续循环时,它会将前一页面中的元素数量添加到当前页面。

所以我的代码是这样的:

driver=webdriver.PhantomJS()
def my_func(start,end)
    while start <= end:
        driver.get('https://www.somerandomsite.com/'+str(start))
        number_of_elements = len(driver.find_elements_by_class_name('some_class'))
        print(number_of_elements)
        start += 1

my_func(1,2)

它打印8然后打印10,就像我想要的那样。我不确定为什么它会同时在两个页面上计算元素,并且只有在事先得到其他页面时才会计算。

EDIT2:所以我通过导航到不同服务器上的页面然后返回到我想要的页面来使其工作。很奇怪,但我会用它。如果我不知道为什么它不起作用,如果我不喜欢我仍然喜欢更好地理解这个问题。

2 个答案:

答案 0 :(得分:1)

很难说出什么 - 如果有的话 - 问题在于你没有提供必要的细节来复制你所描述的内容。

恕我直言,这项简单任务的功能太过分了。只需抛掷它并创建循环。一般来说,我把循环放在外面。

此外,您还需要一个函数调用来执行任何操作 - 以及返回语句。

一般来说,对于类似的东西,我把循环放在函数之外。

像这样:

def my_func(driver, count):
    driver.get('https://www.somerandomsite.com/%d' % count)
    number_of_elements = len(driver.find_elements_by_class_name('some_class'))
    return number_of_elements

driver=webdriver.PhantomJS() 
total_element_count = 0
count = 1
while count < 1000: # or whatever number you need
    number_of_elements = my_func(driver, count)
    total_element_count += number_of_elements
    print("[*] Elements for iteration %d: %d" % (count, number_of_elements))
    print("[*] Total count so far: %d" % total_element_count)
    count +=1

答案 1 :(得分:0)

看看

number_of_elements = len(driver.find_elements_by_class_name('some_class'))

您在每次迭代时都会对元素进行对齐,但您需要对它们求和,因此您的代码应如下所示:

driver=webdriver.PhantomJS()
def my_func(start,end):
    count = 0
    while start <= end:
        driver.get('https://www.somerandomsite.com/'+str(start))
        count += len(driver.find_elements_by_class_name('some_class'))
        start += 1