使用Selenium Basic(VBA)循环一组页面

时间:2018-04-18 09:45:01

标签: excel vba excel-vba selenium-webdriver web-scraping

任务:

所以我第一次涉足Selenium而我正试图:

  1. 查找https://codingislove.com/底部列出的分页集中的页数。这纯粹是为了通过确定循环结束来支持任务2。
  2. 循环过来
  3. 我认为这些是相关的,但对于那些想要单一问题的人来说。我只是想找到正确的集合并在其上循环以加载每个页面。

    在撰写本文时,页面数量为6,如网页底部所示,如下所示:

    Pagination set

    作为一名MCVE,我只是想找到页数并点击我的方式。使用Selenium Basic。

    我尝试了什么:

    我已经阅读了很多在线资源,我已经列出了一些参考资料。

    任务1)

    似乎我应该能够使用Size属性找到页数。但我似乎无法找到使用它的正确对象。我做了很多尝试;一些如下所示:

    bot.FindElementsByXPath("//*[@id=""main""]/nav/div/a[3]").Size '<==this I think is too specific
    bot.FindElementsByClass("page-numbers").Size
    

    但这些会产生运行时错误438:

      

    &#34;对象不支持此属性或方法&#34;

    以下似乎没有公开所需的方法:

    bot.FindElementByCss(".navigation.pagination")
    

    我捏造了

    bot.FindElementsByClass("page-numbers").Count + 1 
    

    但是想要更健壮的东西

    任务2)

    我知道我可以从第1页导航到下一页,其中包含:

    bot.FindElementByXPath("//*[@id=""main""]/nav/div/a[3]").Click
    

    但我不能在循环中使用它,大概是因为需要更新XPath。 如果没有更新,则会导致运行时错误13。

    Run-time error 13

    由于重新指示遵循

    的一般模式
    href="https://codingislove.com/page/pageNumber/"
    

    我可以通过使用

    构建循环中的每个URL来再次捏造我的方式
    bot.Get "https://codingislove.com/page/" & i & "/"
    

    但我想要更强大的东西。

    问题:

    如何使用selenium以健壮的方式遍历分页集?当然我有一个密集的日子,并且应该有一个易于定位的适当集合来循环。

    代码 - 我当前的尝试

    Option Explicit
    Public Sub scrapeCIL()
        Dim bot As New WebDriver, i As Long, pageCount As Long
    
        bot.Start "chrome", "https://codingislove.com"
        bot.Get "/"
        pageCount = bot.FindElementsByClass("page-numbers").Count + 1 '
    
        For i = 1 To pageCount 'technically can loop from 2 I know!
          ' bot.FindElementByXPath("//*[@id=""main""]/nav/div/a[3]").Click 'runtime error 13
           ' bot.FindElementByXPath("//*[@id=""main""]/nav/div/a[2]/span").Click ''runtime error 13
            bot.Get "https://codingislove.com/page/" & i & "/"
        Next i
    
        Stop
    
        bot.Quit
    End Sub
    

    注意:

    任何支持的浏览器都可以。它不一定是Chrome。

    参考文献:

    1. Finding the number of pagination buttons in Selenium WebDriver
    2. http://seleniumhome.blogspot.co.uk/2013/07/how-can-we-automate-pagination-using.html
    3. 要求:

      1. Selenium Basic
      2. ChromeDriver 2.37&#39;或使用IE但缩放必须为100%
      3. VBE工具&gt;参考&gt; Selenium类型库

4 个答案:

答案 0 :(得分:3)

click元素,它必须在屏幕上可见,因此您需要先滚动到页面底部(硒可能会隐式地执行此操作,但我无法找到它可靠)。

试试这个:

Option Explicit
Public Sub scrapeCIL()
    Dim bot As New WebDriver, btn As Object, i As Long, pageCount As Long

    bot.Start "chrome", "https://codingislove.com"
    bot.Get "/"
    pageCount = bot.FindElementsByClass("page-numbers").Count

    For i = 1 To pageCount

        bot.ExecuteScript ("window.scrollTo(0,document.body.scrollHeight);")

        Application.wait Now + TimeValue("00:00:02")

        On Error Resume Next
        Set btn = bot.FindElementByCss("a[class='next page-numbers']")
        If btn.IsPresent = True Then
            btn.Click
        End If
        On Error GoTo 0

    Next i

    bot.Quit

End Sub

答案 1 :(得分:1)

这样试试怎么样?几天前我可以发现有一个选项.SendKeys("keys.END")会引导您到页面底部,这样驱动程序就可以触及预期的点击元素。我在If Err.Number <> 0 Then Exit Do中使用了do loop,因此如果刮刀遇到任何错误,那么在点击element not found error的情况下,last page就会出现问题。按钮完成。

试一试:

Sub GetItems()
    Dim pagenum As Object

    With New ChromeDriver
        .get "https://codingislove.com/"

        Do
            On Error Resume Next
            Set pagenum = .FindElementByCss("a.next")
            pagenum.SendKeys ("Keys.END")
            Application.Wait Now + TimeValue("00:00:03")
            pagenum.Click
            If Err.Number <> 0 Then Exit Do
            On Error GoTo 0
        Loop
        .Quit
    End With
End Sub

参考添加到库:

Selenium Type Library

答案 2 :(得分:0)

如果您只对点击每个页面感兴趣(并且获取页面数量只是帮助这样做)那么您应该能够点击此元素直到它不再有:

<span class="screen-reader-text">Next Page</span>

使用

bot.FindElementByXpath("//span[contains(text(), 'Next Page')]")

在每个页面加载时点击该链接循环。最终它不会在那里。然后使用VBA的错误/异常处理来处理WebDriver的这个实现中等效的NoSuchElementException。每次循环时都需要重新找到元素。

答案 3 :(得分:0)

类似的原则:

Option Explicit

Public Sub GetItems()
    Dim i As Long

    With New ChromeDriver
        .Get "https://codingislove.com/"

        For i = 1 To 6
            .FindElementByXPath("//*[@id=""main""]/nav/div/a[3]").SendKeys ("Keys.PageDown")

            Application.Wait Now + TimeValue("00:00:02")
            On Error Resume Next
            .FindElementByCss("a.next").Click
            On Error GoTo 0
        Next i
    End With
End Sub

参考:

&#39; http://seleniumhome.blogspot.co.uk/2013/07/how-to-press-keyboard-in-selenium.html