gpt4 book ai didi

vba - 无法让我的脚本继续使用IE单击“加载更多”按钮

转载 作者:行者123 更新时间:2023-12-04 20:27:42 25 4
gpt4 key购买 nike

我已经使用IE在vba中创建了一个脚本,以不断单击位于网页底部的Load more hits按钮,直到没有剩下这样的按钮为止。


这是我的脚本填充该按钮的方式:在网站的登录页面中,有一个名为Type的下拉列表。脚本可以单击该Type展开dropdown,然后单击选项中的某些corporate bond复选框。最后,它单击apply按钮以填充数据。但是,该load more hits按钮现在可以在底部看到。


我的脚本几乎可以按照我上面描述的那样执行几乎所有步骤。我唯一要解决的问题是,单击该按钮3/4次后,脚本似乎卡住了。

如何纠正我的脚本,以继续单击该Load more hits按钮,直到没有剩余的按钮为止?

Website link

到目前为止,我已经尝试过:

Sub ExhaustLoadMore()
Dim IE As New InternetExplorer, I As Long
Dim Html As HTMLDocument, post As Object, elem As Object
Dim CheckBox As Object, btnSelect As Object

With IE
.Visible = True
.navigate "https://www.boerse-stuttgart.de/en/tools/product-search/bonds"
While .Busy Or .readyState < 4: DoEvents: Wend
Set Html = .document

Do: Loop Until Html.querySelectorAll(".bsg-loader-ring__item").Length = 0

Html.querySelector("#bsg-filters-btn-bgs-filter-3").Click
Do: Set CheckBox = Html.querySelector("#bsg-checkbox-3053"): DoEvents: Loop While CheckBox Is Nothing
CheckBox.Click

Set btnSelect = Html.querySelector("#bsg-filters-menu-bgs-filter-3 .bsg-btn__label")
Do: Loop While btnSelect.innerText = "Close"
btnSelect.Click

Do: Loop Until Html.querySelectorAll(".bsg-loader-ring__item").Length = 0
Do: Set elem = Html.querySelector(".bsg-table__tr td"): DoEvents: Loop While elem Is Nothing

Do
Set post = Html.querySelector(".bsg-searchlist__load-more button.bsg-btn--juna")
If Not post Is Nothing Then
post.ScrollIntoView
post.Click
Application.Wait Now + TimeValue("00:00:05")
Else: Exit Do
End If
Loop
End With
End Sub


我尝试过硒,但似乎慢得多。但是,即使在其中没有硬编码等待的情况下,经过很长的等待时间之后,它仍会继续单击“加载更多”按钮。在硒的情况下:我希望有任何可能有助于减少执行时间的解决方案。

Sub ExhaustLoadMore()
Const Url$ = "https://www.boerse-stuttgart.de/en/tools/product-search/bonds"
Dim driver As New ChromeDriver, elem As Object, post As Object

With driver
.get Url
Do: Loop Until .FindElementsByCss(".bsg-loader-ring__item").count = 0
.FindElementByCss("#bsg-filters-btn-bgs-filter-3", timeOut:=10000).Click
.FindElementByXPath("//label[contains(.,'Corporate Bond')]", timeOut:=10000).Click
.FindElementByXPath("//*[@id='bsg-filters-menu-bgs-filter-3']//button", timeOut:=10000).Click
Do: Loop Until .FindElementsByCss(".bsg-loader-ring__item").count = 0
Set elem = .FindElementByCss(".bsg-table__tr td", timeOut:=10000)
Do
Set post = .FindElementByCss(".bsg-searchlist__load-more button.bsg-btn--juna", timeOut:=10000)
If Not post Is Nothing Then
post.ScrollIntoView
.ExecuteScript "arguments[0].click();", post
Do: Loop Until .FindElementsByCss("p.bsg-searchlist__info--load-more").count = 0
Else: Exit Do
End If
Loop
Stop
End With
End Sub

最佳答案

我研究了您的网站,并且由于无法将所有这些都都发表在一个评论中,所以我决定发布一个答案(即使它没有提供具体的解决方案,但仅提供了“答案”,也许一些技巧)。

您问题的答案


我如何纠正我的脚本,以继续单击该“加载更多点击”按钮,直到没有剩余的按钮为止?


不幸的是,这不是你的错。您定位的网站正在通过Web客户端(您的浏览器)和Web服务器之间的WebSocket通信工作,并提供您要抓取的价格。您可以看到如下:

enter image description here

像这样想象:


首次加载网页时,将初始化Web套接字并发送第一个请求(Web客户端:“嘿,服务器,请给我我的第一个X结果”,Web服务器:“当然,到这里开始”)。
每次单击“加载更多结果”按钮时,Web客户端(重要:重新使用相同的WS连接)都会不断向Web服务器请求X个新结果。


因此,通信持续进行了一段时间。有时,您无法控制Web套接字的死机。在单击“加载更多结果”按钮时查看JavaScript控制台就足够了:您将看到请求正在进行,直到在某个时候您不仅看到了NullPointerException

enter image description here

如果单击例外之前堆栈的最后一行,您将看到是由于Web套接字造成的:

enter image description here

该错误明确说明:cannot read .send() on null,表示_ws(Web套接字)已消失。

从现在开始,您可以忘记您的网站。当您单击按钮“加载更多结果”时,Web客户端将要求Web套接字将新请求传递到Web服务器,但是Web套接字已经消失了,两者之间的通信太远了,因此(不幸地)告别了。其余数据。

您可以通过在堆栈中靠前一点来验证这一点:

enter image description here

如您在上面看到的,我们有:


在发布新数据请求之前,在控制台中记录了一条消息,内容为“ performSearch params ...”。
新数据请求的post
刚发布新的数据请求后,在控制台中记录了一条消息,内容为“执行了搜索并显示了结果...”)


当Web套接字仍处于活动状态时,每次您单击“加载更多结果”时,您都会在控制台中看到以下两条消息(其他消息则显示在其其余代码中):

enter image description here

但是,在Web套接字第一次崩溃后,无论您尝试单击该按钮多少次,您都只会收到第一条消息(Web客户端发送请求),而永远不会收到第二条消息(请求在无效):

enter image description here

请注意,这与您在VBA中观察到的行为相对应:


单击该按钮3/4次后,脚本似乎卡住了。


它不会卡住,实际上您的脚本可以继续正确执行。是网站超时。

我试图弄清楚为什么Web套接字崩溃了,但是没有运气。似乎只是超时(我在调试其JavaScript时遇到了很多事情,所以我的断点导致了超时),但我无法确定这是唯一的原因。由于您不控制Web客户端和Web服务器之间的过程,因此您所要做的就是希望它不会超时。

另外,我相信使用Selenium会自动设置一些较长的超时时间(由于执行时间长),因此可以使Web套接字在超时方面更加容忍。

我发现在Web套接字崩溃后恢复连接的唯一方法是完全重新加载网页并从头开始重新启动该过程。

我的建议

我认为您可能会构建一个XHR请求并通过JavaScript发送,因为它们的API(Web客户端/ Web套接字通过该API将请求传递到Web服务器)已在其前端代码中公开了。

如果打开他们的文件FinderAPI.js,您将看到他们离开了端点,并且对API配置进行了编码:

var FinderAPI = {
store: null,
state: null,
finderEndpoint: '/api/v1/bsg/etp/finder/list',
bidAskEndpoint: '/api/v1/prices/bidAsk/get',
instrumentNameEndpoint: '/api/products/ProductTypeMapping/InstrumentNames',
nameMappingEndpoint: '/api/v1/bsg/general/namemapping/list',
apiConfig: false,
initialize: function initialize(store, finderEndpoint) {
var apiConfig = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
this.store = store;
this.state = store.getState();
this.apiConfig = apiConfig;
this.finderEndpoint = finderEndpoint;
},


这意味着您知道应将 POST请求发送到的URL。

请求还需要由服务器验证承载令牌。幸运的是,他们还忘记保护令牌,而提供(ccs)端点以获得令牌的 GET

端点: https://www.boerse-stuttgart.de/api/products

响应:
{“ AuthenticationToken”:“ JgACxn2DfHceHL33uJhNj34qSnlTZu4 + hAUACGc49UcjUhmLutN6sqcktr / T634vaPVcNzJ8sHBvKvWz”,“主机”:“ frontgate.mdgms.com”}

您只需要稍微浏览一下网站即可确定POST请求的内容,然后创建一个新的 XmlHttpRequest并发送其中的值以直接在您的VBA中检索价格,而无需打开网页和自动抓取。

我建议您从文件 FinderAPI.js的断点开始,行66(代码行是 this.post(this.finderEndpoint, params)params应该将您引向请求的正文-我记得您可以使用< cc>)。

另外,请注意,即使它们的API最多支持 JSON.stringify(params)个,它们也会使用 50个结果的分页。换句话说,如果您将值500(而不是50)扫入发送给API的请求的分页属性中:

enter image description here

...那么您每次将获得500个结果,而不是50个,因此,如果您决定不更深入地研究XHR解决方案,那么您的代码将花费在抓取网页上的时间减少了10分钟。

关于vba - 无法让我的脚本继续使用IE单击“加载更多”按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55069943/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com