我一直在使用Excel中的HTML,试图估算不同分辨率的常见图像。我希望得到一些动态的东西 - 用户输入一个搜索词,代码循环通过一组预定义的图像分辨率,对指定分辨率之间的搜索词的常见图像进行排序。
第一步是获得以特定分辨率返回图像数量的可靠(快速)方式。我写了这段代码:
Sub GoogleWithURL() 'requires Microsoft HTML Object Library
Dim url As String, searchTerm As String
Dim objIE As InternetExplorer 'special object variable representing the IE browser
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("sheet1")
Dim currPage As HTMLDocument
Dim xRes As Integer, yRes As Integer
With ws
xRes = .Range("XRes")
yRes = .Range("YRes")
searchTerm = .Range("search")
End With
'create URL to page with these image criteria
url = WorksheetFunction.Concat("https://www.google.com/search?q=", searchTerm, _
"&tbm=isch&source=lnt&tbs=isz:ex,iszw:", xRes, "iszh:", yRes)
'initiating a new instance of Internet Explorer and asigning it to objIE
Set objIE = New InternetExplorer
'objIE.Visible = True 'for debugging purposes
'Google images search
objIE.navigate url
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Set currPage = objIE.document
'Count image results
Set valueResult = currPage.getElementById("rg_s").getElementsByTagName("IMG")
MsgBox WorksheetFunction.Concat("'", searchTerm, "' returns ", valueResult.Length _
, " images @ ", xRes, "x", yRes, "px.") 'returns number of loaded images on page
'close the browser
On Error Resume Next 'required when the browser is visible and I close it manually half way
objIE.Quit
End Sub
它将Internet Explorer对象导航到特定分辨率谷歌图片搜索,计算rg_s
ID中的图像数量(这些是图像结果而不是横幅图像等)。然后它将该计数作为消息框返回。 (当我最终实现这一点时,我将在工作表的一列中返回值,循环显示30个不同的分辨率)
此代码的主要问题是:
它没有给出非常有用的计数。 分辨率很低,因为它只对已加载的图像进行计数 - 这意味着大多数搜索条件(如1920x1080或1366x768)会返回最多100张图像。
很慢。对我来说,导航到页面,计算图像标签,这看起来很像在VBA中使用.Select
。这就像手动方法,人类会做什么,因此效率低下。
我可以想出一些解决这些问题的方法
解决数据/获得更有用的计数
向下滚动。如果我可以加载更多图像,我可能会更好地区分。我发现尽可能向下滚动(直到'加载更多结果'按钮)给出400不是100的上限 - 如果给定分辨率至少有那么多图像那么我很开心,我会把它排在最前面。但是对问题2没有帮助。不过,我该怎么做?
缩小搜索结果。如果返回100,我可以更改我发送的URL中的filetype:
,例如附加filetype:png
可以将返回的图像数量减半,从而在0-100范围内给出更好的传播。虽然不太理想,因为我必须为某些分辨率迭代多个文件类型,减慢代码速度,甚至不一定给我我想要的东西。
使用Google(或其他搜索引擎)自己的值。我已经在各种网站上以各种形式询问了这一点,是否有任何直接来自Google的图像数据 - 即没有返回(并缓慢加载)图像本身。就像常规搜索的about 1,300,500 results in 0.03 seconds
一样,仅适用于图像?如果我每次采样一个比100个结果更大的数组时使用预先计算的值,我可能会得到更详细的图片。
慢度
CreateObject("MSXML2.serverXMLHTTP")
。不知道其中任何一个,但如果你认为它们是更好的方式,那么我会更仔细地研究它们。摘要
希望能够继续下去,我认为我的思路应该相当清楚。关于如何向下滚动/加载更多图像/让Google返回计数而非图像本身的实际答案将是最好的,关于应该采取什么的建议也是有用的。
答案 0 :(得分:1)
你的瓶颈不在for循环中。它打开浏览器并将其指向某个位置。如果您担心时间,那么您应该抓住已经对该页面打开的浏览器,并且在您对其运行所有搜索之前不要关闭它。每次搜索至少应保存2秒。我运行了以下代码并得到了这些时间:
打开并设置资源管理器的时间:2.41秒。
计算100张照片的时间(1):0.1秒。
计算100张照片的时间(2):0.11秒。
我们的方法之间的差异是1/100秒。
此外,Google图片要求用户向下翻页,以便拨打下一张100张图片。如果您可以找到ajax或javascript语句来实现这一点,那么您将能够让它认为它已经关闭了页面。这就是为什么你只能获得100张图像的原因。
或者您可以打开浏览器,输入搜索字词,然后向下翻页,直到屏幕上显示299张图片,此时您会找到一个显示&#34;显示更多图片&#34;的按钮。然后抓住那个打开的网页。
如果您运行多个搜索字词而不是时间瓶颈在于打开和关闭浏览器,那么不计算图像。
Sub GoogleWithURL() 'requires Microsoft HTML Object Library
' https://www.google.com/search?q=St+Mary&source=lnms&tbm=isch&sa=X&ved=0ahUKEwj99ay14aPSAhWDMSYKHadiCjkQ_AUICSgC&biw=1600&bih=840
Dim url As String
Dim objIE As InternetExplorer 'special object variable representing the IE browser
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim currPage As HTMLDocument
Dim StartTime As Double, SecondsElapsed As Double
'****************************************
' Hard code url to search images of St Mary
url = "https://www.google.com/search?q=St+Mary&source=lnms&tbm=" & _
"isch&sa=X&ved=0ahUKEwj99ay14aPSAhWDMSYKHadiCjkQ_AUICSgC&biw=1600&bih=840"
StartTime = Timer
Set objIE = New InternetExplorer
objIE.Visible = True
objIE.navigate url
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Set currPage = objIE.document
SecondsElapsed = Round(Timer - StartTime, 2)
Debug.Print "Time to open and set Explorer: " & SecondsElapsed & " seconds."
StartTime = Timer
Set valueResult = currPage.getElementById("rg_s").getElementsByTagName("IMG")
For Each pic In valueResult
counter = counter + 1
Next pic
SecondsElapsed = Round(Timer - StartTime, 2)
Debug.Print "Time to Count " & counter & " Photos(1): " & SecondsElapsed & " seconds."
counter = 0
StartTime = Timer
Set valueResult = currPage.getElementsByTagName("IMG")
For Each pic In valueResult
If InStr(1, pic.className, "rg") > 0 Then
counter = counter + 1
End If
Next pic
SecondsElapsed = Round(Timer - StartTime, 2)
Debug.Print "Time to Count " & counter & " Photos(2): " & SecondsElapsed & " seconds."
On Error Resume Next 'required when the browser is visible and I close it manually half way
objIE.Quit
End Sub
答案 1 :(得分:0)
经过几个问题,现在感觉有点明智了,我为此制作了一个UDF:
Public Function GOOGLE_COUNT(searchTerm As String, xRes As Long, yRes As Long, Optional timeout As Long = 10) As Long
Dim url As String
Dim objIE As InternetExplorer
Dim currPage As HTMLDocument
Dim stTimer As Double, tElapsed As Single
Dim valueResult As IHTMLElementCollection
'create URL to page with these image criteria
url = "https://www.google.com/search?q=" & searchTerm & _
"&tbm=isch&source=lnt&tbs=isz:ex,iszw:" & xRes & ",iszh:" & yRes
'initiating a new instance of Internet Explorer and asigning it to objIE
Set objIE = New InternetExplorer
'Google images search
objIE.navigate url
Do While objIE.Busy = True Or objIE.readyState <> 4: DoEvents: Loop
Set currPage = objIE.document
Dim myDiv As HTMLDivElement: Set myDiv = currPage.getElementById("fbar")
Dim elemRect As IHTMLRect: Set elemRect = myDiv.getBoundingClientRect
stTimer = Timer
'Scroll until bottom of page is in view
Do Until elemRect.bottom > 0 Or tElapsed > timeout 'timeout after n seconds
currPage.parentWindow.scrollBy 0, 10000
Set elemRect = myDiv.getBoundingClientRect
tElapsed = Timer - stTimer
Loop
myDiv.ScrollIntoView
'Count the images
Set valueResult = currPage.getElementById("rg_s").getElementsByTagName("IMG")
GOOGLE_COUNT = valueResult.Length
objIE.Quit
End Function
像这样工作:以1366:768图像大小搜索“圣玛丽”然后
=GOOGLE_COUNT("St. Mary", 1366, 768)
或者超时10秒(如果已经过了10秒,搜索会停止滚动,只计算加载的图像)
=GOOGLE_COUNT("St. Mary", 1366, 768, 10)
我在another question中解释滚动是如何工作的,它现在很乱,但很实用。
正如@John Muggins所指出的那样,所花费的大量时间是装载,而不是计算。特别是,打开和关闭InternetExplorer
。所以要避免大量的重新计算时间;如果(像我一样)你想检查多个术语/分辨率,将此代码放在宏中,而不是函数(如果您认为我应该发布此评论,请发表评论)。 此UDF仅适用于一次性搜索
希望它有用,我想我应该重新访问这个问题来发布我得到的答案。
最后注意事项:
您的计算机(可能)没有崩溃,该功能只是计算。
对于搜索字词,请键入您在Google搜索栏中输入的内容 - 例如“Jaguar -car”返回动物的图像,而非汽车公司
结果是0-400; 0-399是实际计算的图像数量(只要你设置超时足够大 - 自动为10秒)。 400是最大值,因此在该分辨率下,该术语可能有超过400张图像。