VBA / VBscripting自动化的Web Scraping循环与IElogin
我一直在试图编写一个脚本,将网站在渲染网站上的某个字段/标签。 该网站与Excel中的列列表中的search参数呈现。 Appox 20个项目将会增长。 在研究如何使用vbscript来抓取网页之后,我遇到的问题是如何做20次而不会中断。 这是我的代码。
Excel列
1492565 1528417 1529041 1530688 1492038 1492319 1492972 1508824 1513351 1514724 1514750 1518526 1520627 1520706 1520979 1523367 1523563
Script:Main sub(从excelinput字段获取用户名/密码,通过特定列上的行设置循环,只有吐出msgbox才能使循环工作,然后输出到另一列
Sub WebScrapper() 'itg on mainWS start row 6, column 5 'itg status column column 19 'declare variables Dim url As String Dim ITGNUMBER As Long Dim user As String Dim pwd As String 'set variables url = "https://website/itg/web/knta/crt/RequestDetail.jsp?REQUEST_ID=" Set oMainWS = ActiveWorkbook.Worksheets("MainWS") Set oITGStatusWS = ActiveWorkbook.Worksheets("ITGStatus") user = "" pwd = "" user = oITGStatusWS.ITGusername.Value pwd = oITGStatusWS.ITGpassword.Value If user = "" Or pwd = "" Then MsgBox ("You must enter username/password before continuing") Exit Sub End If 'log in Set objIE = FirstIEConnect(user, pwd) 'start row is 6 RowCounter = 58 ColumnCounter = 5 ITGStatusColumn = 16 Do Until IsEmpty(oMainWS.Cells(RowCounter, 5).Value) 'get ITG number currentITGNumber = oMainWS.Cells(RowCounter, 5).Value MsgBox (currentITGNumber) 'get remote status currentITGStatus = getITGStatusFunction(objIE.Application, Str(currentITGNumber)) MsgBox (currentITGStatus) 'paste into column 19 'oMainWS.Cells(RowCounter, 19).Value = currentITGStatus 'increment counter RowCounter = RowCounter + 1 currentITGStatus = "" currentITGNumber = "" Loop quitIE (objIE.Application) End Sub
Sub来退出对象清理,有一个javascript函数来把用户登出。
Sub quitIE(obj As Object) obj.Navigate ("javascript: closeChildWindowsAndLogout();") obj.Quit End Sub
从谷歌得到这个子,用来等待IE对象准备就绪。 这实际上在循环中失败了很多。 在做,而IE.Busy:循环。 只是挂起。
Sub Wait(obj As Object) Do While obj.Busy: Loop Do While obj.readyState <> 4: Loop Application.Wait (Now + TimeValue("0:00:01")) End Sub
该网站需要login,用户/ pwd是从第一个子。 这个子创buildIE对象,导航到login页面,并将user / pwd插入Document.logon.UserName
和Document.logon.Password
。 最后提交。
Function FirstIEConnect(user As String, pwd As String) loginURL = "https://website/Logon.jsp" Set IE = CreateObject("InternetExplorer.Application") IE.Visible = False IE.Navigate loginURL Wait (IE.Application) With IE.Document.logon .UserName.Value = user .Password.Value = pwd .submit End With Set FirstIEConnect = IE End Function
这是实际的网页抓取function。 要求用户从上面loginIE对象。 将numinput到url GET请求中以呈现特定页面。 最后抓取基于ElementID的responseText
Function getITGStatusFunction(obj, num) On Error Resume Next 'set url and num url = "https://website/RequestDetail.jsp?REQUEST_ID=" & num obj.Navigate url Wait (obj.Application) responseText = obj.Document.getElementByID("DRIVEN_STATUS_ID").innerHTML getStatusFunction = responseText End Function
再次,问题是,当我试图从不同的子和函数传递IE对象时,我总是收到对象错误。
期望:我希望脚本遍历Excel中包含唯一编号的列信息。 把这些数字逐一join到searchurl中。 一旦页面加载了ElementID(DRIVEN_STATUS_ID)
。 最终将这个值输出到另一列。
Wait (IE)
传递IE.Name
而不是对象。 要传递对象,请使用IE.Application
。
蒂姆·威廉姆斯的评论也是正确的,舍弃括号也会导致对象被传递。 所以Wait IE
而不是Wait (IE)
也将工作。 但是我认为使用Wait IE.Application
安全。 显然,你决定。
如果你要更新等待function,它仍然不能解决这个问题,但是在问题出现的地方会更加明显。 Function Wait(IE as object)
尝试调用函数时失败,说明需要一个对象。
这应该是显而易见的,但是不要通过IE
,在所有情况下IE.Application
传递IE.Application
,除非你真的只想要对象的名字。
顺便说一下, Set variable = IE
行很好,因为关键字Set
使得它清楚你想要的对象。
只是在黑暗中拍摄,但这听起来像HTML尝试设置值时未完全加载。 尝试使用更长的等待值。 通常3-4秒钟就可以完成。
或者你可以创build一个新的variables,并设置一个循环,直到对象被设置为止:
Dim obj_testVariable as Object Do Until Not obj_testVariable Is Nothing set obj_testVariable = obj.Document.getElementByID("DRIVEN_STATUS_ID") Loop responseText = obj_testVariable.innerHTML set obj_testVariable = Nothing
(另)
这是我的IEWait
function:
Dim IE As Object Function IEWait(t As Long) Do While IE.Busy Application.Wait DateAdd("s", t, Now) Loop End Function
你可以在你的子程序中使用它:
IEWait (1) Do Until IE.readyState = READYSTATE_COMPLETE: DoEvents: Loop
提交内容时,只能使用第一行,而在加载新页面时使用两行。 只是玩耍,这将需要一些时间。 祝你好运。