使用 XMLHTTP 方法时等到页面加载完毕
Posted
技术标签:
【中文标题】使用 XMLHTTP 方法时等到页面加载完毕【英文标题】:Wait until page is loaded when using XMLHTTP approach 【发布时间】:2020-02-03 13:53:41 【问题描述】:在以下工作代码中,我正在尝试导航到特定的 youtube 频道 要将视频名称转换为 excel .. 它正在工作,但部分是因为代码只列出了大约 30 个视频
Dim x, html As Object, ele As Object, sKeyWords As String, i As Long
With CreateObject("MSXML2.ServerXMLHTTP")
.Open "GET", "youtube channel url videos", False
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.send
If .Status <> 200 Then MsgBox "Problem" & vbNewLine & .Status & " - " & .statusText: Exit Sub
Set html = CreateObject("htmlfile")
html.body.innerHTML = .responseText
我怎样才能使代码加载页面的所有内容..?以便获取那里列出的所有视频。
我找到了一个网站,将所有视频都列在一个表格中,但是对于抓取表格的部分,我无法提取视频名称,甚至无法处理表格 这是我的尝试
Sub Post_Method()
Dim http As New XMLHTTP60
Dim html As New HTMLDocument
Dim htmla As Object
Dim trow As Object
Dim tcel As Object
Dim strArg As String
Dim c As Long
Dim x As Long
strArg = "inputType=1&stringInput=https%3A%2F%2Fwww.youtube.com%2Fchannel%2FUC43lrLHl4EhxaKQn2HrcJPQ&limit=100&keyType=default&customKey="
With http
.Open "POST", "https://youtube-playlist-analyzer.appspot.com/submit", False
.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
.send strArg
html.body.innerHTML = .responseText
' WriteTxtFile html.body.innerHTML
End With
Dim posts As Object, elem As Object, r As Long
'This part I can't adjust
'------------------------
Set posts = html.getElementById("container").getElementById("tableContainer").getElementById("tableData")
For Each elem In posts.Children
For Each trow In elem.Cells
c = c + 1: Cells(r + 1, c) = trow.innerText
Next trow
c = 0: r = r + 1
Next elem
'----------------------------------
Stop
End Sub
【问题讨论】:
您意识到 YouTube 经常会在您滚动页面时动态加载很多内容 - 您是否检查过这是否是一个因素? 非常感谢。我注意到。所以我问了这个问题,可能有一种解决方法可以使页面完全加载... 我的直觉是硒和慢滚动可能是最好的方法,但我还没有测试过。 谢谢。你能指导我如何在 selenium 中使用滚动 ..? 应该有关于 SO 的例子,尤其是在 python 标签中。缓慢滚动,直到没有更多结果。用户 alexce 对此写了一个众所周知的答案——除非你能阅读 python,否则我认为它没有多大帮助。用户 sim 可能在此处或代码审查中用 vba selenium 编写了等效的代码。 【参考方案1】:您可以使用该端点,然后从包含感兴趣数据的响应中提取 javascript 对象并使用 jsonconverter.bas 进行解析。
Json 库:
我使用 jsonconverter.bas。从here 下载原始代码并添加到名为 JsonConverter 的标准模块中。然后您需要转到 VBE > 工具 > 参考 > 添加对 Microsoft Scripting Runtime 的引用。从复制的代码中删除顶部的 Attribute 行。
VBA:
Option Explicit
Public Sub GetYouTubeViews()
Dim s As String, ws As Worksheet, body As String
body = "inputType=1&stringInput=https://www.youtube.com/channel/UC43lrLHl4EhxaKQn2HrcJPQ&limit=100&keyType=default"
Set ws = ThisWorkbook.Worksheets("Sheet1")
With CreateObject("MSXML2.XMLHTTP")
.Open "POST", "https://youtube-playlist-analyzer.appspot.com/submit", False
.setRequestHeader "User-Agent", "Mozilla/5.0"
.send body
s = .responseText
End With
Dim results(), r As Long, jsonSource As String
Dim json As Object, item As Object, headers()
jsonSource = GetString(s, "json_items = ", ";")
If jsonSource = "No match" Then Exit Sub
Set json = JsonConverter.ParseJson(jsonSource)
headers = Array("Title", "ViewCount")
ReDim results(1 To json.Count, 1 To UBound(headers) + 1)
For Each item In json
r = r + 1
results(r, 1) = item("title")
results(r, 2) = item("viewCount")
Next
With ws
.Cells(1, 1).Resize(1, UBound(headers) + 1) = headers
.Cells(2, 1).Resize(UBound(results, 1), UBound(results, 2)) = results
End With
End Sub
Public Function GetString(ByVal inputString As String, ByVal startPhrase As String, ByVal endPhrase As String) As String
Dim s As Long, e As Long
s = InStr(inputString, startPhrase)
If Not s > 0 Then
GetString = "No match"
Exit Function
End If
e = InStr(s + Len(startPhrase) - 1, inputString, endPhrase)
If Not e > 0 Then
GetString = "No match"
Exit Function
End If
GetString = Mid$(inputString, s + Len(startPhrase), e - (s + Len(startPhrase)))
End Function
示例结果:
派:
使用 python 更简洁
import requests, re, json ,csv
data =
'inputType': '1',
'stringInput': 'https://www.youtube.com/channel/UC43lrLHl4EhxaKQn2HrcJPQ',
'limit': '100',
'keyType': 'default'
r = requests.post('https://youtube-playlist-analyzer.appspot.com/submit', data=data)
p = re.compile(r'json_items = (.*?);', re.DOTALL)
results = json.loads(p.findall(r.text)[0])
with open("data.csv", "w", encoding="utf-8-sig", newline='') as csv_file:
w = csv.writer(csv_file, delimiter = ",", quoting=csv.QUOTE_MINIMAL) #change this for locale
w.writerow(['Title','ViewCount'])
for item in results:
w.writerow([item['title'], item['viewCount']])
【讨论】:
太棒了。非常棒。非常感谢,至于刮桌的部分,究竟是什么问题,我根本无法处理……? 我认为该表是由响应中的 JavaScript 指令动态构建的。如果是这种情况,则需要浏览器来填充表格。 您需要打印响应而不是让它到达 jsonconverter。是的,我今天晚些时候会看看。 我稍后再看 我已经找到原因了。有一个带有分号描述的视频,所以我更改了这一行jsonSource = GetString(s, "json_items = ", ";" & vbLf & vbLf)
,现在效果很好以上是关于使用 XMLHTTP 方法时等到页面加载完毕的主要内容,如果未能解决你的问题,请参考以下文章