【发布时间】:2021-11-24 15:06:49
【问题描述】:
我正在尝试从webpage 中提取street address 和builder name。当我使用 xmlhttp60 请求时,我会相应地获取这些字段。但是,当我提出serverxmlhttp60 请求时,大多数时候我都会得到部分响应,因此脚本只打印street adddress。我使用json converter 从该站点的json 内容中解析出builder name。
这是概念证明:
Sub GrabPropertyInfo()
Const siteLink$ = "https://www.redfin.com/TX/Austin/604-Amesbury-Ln-78752/unit-2/home/171045975"
Dim oPost As Object, oData As Object, Html As HTMLDocument
Dim jsonObject As Object, jsonStr As Object, propertyMainRaw$
Dim itemStr As Variant, sResp As String, oElem As Object
Dim propertyContainer As Object, propertyMain As Object
Set Html = New HTMLDocument
' With CreateObject("MSXML2.XMLHTTP")
' .Open "GET", siteLink, False
' .setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36"
' .send
' sResp = .responseText
' Html.body.innerHTML = .responseText
' End With
With CreateObject("MSXML2.ServerXMLHTTP.6.0")
.Open "GET", siteLink, True
.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36"
.send
While .readyState < 4: DoEvents: Wend
sResp = .responseText
Html.body.innerHTML = .responseText
End With
Debug.Print "Street address: " & Html.querySelector("h1.homeAddress > .street-address").innerText
With CreateObject("VBScript.RegExp")
.Global = True
.Pattern = "reactServerState\.InitialContext = (.*);"
.MultiLine = True
Set jsonStr = .Execute(sResp)
End With
itemStr = jsonStr(0).submatches(0)
Set jsonObject = JsonConverter.ParseJson(itemStr)
Set propertyMain = jsonObject("ReactServerAgent.cache")("dataCache")("/stingray/api/home/details/mainHouseInfoPanelInfo")("res")
propertyMainRaw = Replace(propertyMain("text"), "{}&&", "")
On Error Resume Next
Set propertyContainer = JsonConverter.ParseJson(propertyMainRaw)("payload")("mainHouseInfo")("amenitiesInfo")("superGroups")
On Error GoTo 0
If Not propertyContainer Is Nothing Then
For Each oElem In propertyContainer
For Each oPost In oElem("amenityGroups")
If InStr(oPost("groupTitle"), "Building Information") > 0 Then
For Each oData In oPost("amenityEntries")
If InStr(oData("amenityName"), "Builder Name") > 0 Then
Debug.Print "Builder Name: " & oData("amenityValues")(1)
End If
Next oData
End If
Next oPost
Next oElem
End If
End Sub
使用 xmlhttp 请求,我总是得到:
Street address: 604 Amesbury Ln #2,
Builder Name: Zach Savage
使用 serverxmlhttp 请求,我大部分时间得到以下结果:
Street address: 604 Amesbury Ln #2,
如何使用 serverxmlhttp 请求获得完整响应?
编辑:
根据答案和 cmets,很明显,如果我使用 xmlhttp 请求从该站点刮取 browserid 并在使用 serverxmlhttp 发送请求时使用该 browserid 的值作为 cookie,我会得到想要的结果。但是,问题是我使用xmlhttp 请求得到的browserid 的值是sz9u0xmCQKKV9Wu0jRa3Yg,而我可以在页面源中看到这个值v-J5D2IUSyqXizI7MG67fQ。我怎样才能得到后一个值?这就是我解析browserid的方式。
Sub FetchBrowserId()
Const siteLink$ = "https://www.redfin.com/TX/Austin/604-Amesbury-Ln-78752/unit-2/home/171045975"
Dim Rxp As Object, browserId As Object, sRes$, cookie$
Set Rxp = CreateObject("VBScript.RegExp")
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", siteLink, False
.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36"
.send
sRes = .responseText
End With
With Rxp
.Global = True
.Pattern = "window.__rfBrowserId=""(.*?)"";"
.MultiLine = True
Set browserId = .Execute(sRes)
End With
cookie = browserId(0).submatches(0)
Debug.Print cookie
End Sub
【问题讨论】:
-
xmlhttp60?如果您的意思是xmlhttp,它应该返回与ServerXMLHTTP.6.0相同的返回值,引用'Microsoft XML,v6.0',我想。试用代码时您是否已登录? -
我使用的正是我在@FaneDuru 上面粘贴的代码。如您所见,我没有在脚本中使用凭据,所以我没有登录。我也没有手动登录。但是,它们(
xmlhttp和ServerXMLHTTP)都应该返回相同的响应,但实际上并非如此。在这里你可以看到一个例外。我想知道如何解决这个问题。谢谢。 -
当前脚本正在使用
ServerXMLHTTP请求。您可以通过取消注释上面的相关部分来使用XMLHTTP60请求。 -
上面的代码返回完全一样,当我测试它...当然,取消注释部分并跳过
ServerXMLHTTP。我在询问有关登录的问题,因为我不知道该站点是否会在登录时公开更多内容。XMLHTTP不关心 cookie,ServerXMLHTTP关心,但是当我尝试解释时进行测试,它们都返回"Street address: 604 Amesbury Ln #2,"... -
为什么你需要来自页面源的
browserid?它与 cookie 有什么关系?
标签: vba web-scraping xmlhttprequest serverxmlhttp