我在寻找一个批处理或PowerShell脚本来搜索使用本地图像作为输入在谷歌图片类似的图片。
我的研究至今
对于使用URL而不是本地文件的图像搜索的语法followes:
https://www.google.com/searchbyimage?image_url=TEST
其中TEST可以与你有任何图像URL来代替。
我打了卷曲的窗户和imgur临时图像保护。 我能上传文件通过一批imgur。 接下来,该图像URL被用来对谷歌搜索类似的图片。
但我不知道是否有可能不使用任何临时缓存像imgur或任何其他在线图片服务。 只是一个批次,卷曲,谷歌和我。
只是一个想法。 是一个VBS脚本也许能够与本地文件作为输入在谷歌图片搜索?
或像类似的网络服务Tineye更适合这项任务?
这PowerShell的片段将打开谷歌图片搜索。
$IE= new-object -com InternetExplorer.Application
$IE.navigate2("https://www.google.com/imghp?hl=en")
while ($IE.busy) {
sleep -milliseconds 50
}
$IE.visible=$true
接下来的步骤将是得到一些按钮的ID,然后点击它们编程来选择本地文件。 但在这里我没有足够的经验来实现这一目标。
酷的问题! 我花了太多的时间与此修补,但我认为终于得到它:)
概括地说,你要上传图片的原始字节,嵌入式和一些其他的东西沿着正确的格式,以images.google.com/searchbyimage/upload
。 该请求的响应将包含发送给您的实际结果页一个新的URL。
该函数将返回结果页面的URL。 你可以做任何你想做的事情,但只要打开浏览器的结果,将它传递给Start-Process
。
当然,谷歌可以随时更改此工作流程,所以不要指望这个剧本永远工作。
function Get-GoogleImageSearchUrl
{
param(
[Parameter(Mandatory = $true)]
[ValidateScript({ Test-Path $_ })]
[string] $ImagePath
)
# extract the image file name, without path
$fileName = Split-Path $imagePath -Leaf
# the request body has some boilerplate before the raw image bytes (part1) and some after (part2)
# note that $filename is included in part1
$part1 = @"
-----------------------------7dd2db3297c2202
Content-Disposition: form-data; name="encoded_image"; filename="$fileName"
Content-Type: image/jpeg
"@
$part2 = @"
-----------------------------7dd2db3297c2202
Content-Disposition: form-data; name="image_content"
-----------------------------7dd2db3297c2202--
"@
# grab the raw bytes composing the image file
$imageBytes = [Io.File]::ReadAllBytes($imagePath)
# the request body should sandwich the image bytes between the 2 boilerplate blocks
$encoding = New-Object Text.ASCIIEncoding
$data = $encoding.GetBytes($part1) + $imageBytes + $encoding.GetBytes($part2)
# create the HTTP request, populate headers
$request = [Net.HttpWebRequest] ([Net.HttpWebRequest]::Create('http://images.google.com/searchbyimage/upload'))
$request.Method = "POST"
$request.ContentType = 'multipart/form-data; boundary=---------------------------7dd2db3297c2202' # must match the delimiter in the body, above
$request.ContentLength = $data.Length
# don't automatically redirect to the results page, just take the response which points to it
$request.AllowAutoredirect = $false
# populate the request body
$stream = $request.GetRequestStream()
$stream.Write($data, 0, $data.Length)
$stream.Close()
# get response stream, which should contain a 302 redirect to the results page
$respStream = $request.GetResponse().GetResponseStream()
# pluck out the results page link that you would otherwise be redirected to
(New-Object Io.StreamReader $respStream).ReadToEnd() -match 'HREF\="([^"]+)"' | Out-Null
$matches[1]
}
用法:
$url = Get-GoogleImageSearchUrl 'C:\somepic.jpg'
Start-Process $url
编辑/解释
下面是一些更多的细节。 我基本上只是把你通过我了,因为我想通了这一点的步骤。
首先,我只是说干就干,做了局部图像搜索。
它发送给你的网址很长(〜在longcat的情况下,1500个字符),但几乎没有足够长的图像(60KB)完全编码。 所以,你可以告诉了蝙蝠的权利,它是不是简单地做一些像一个base64编码更为复杂。
接下来,我发射了小提琴手,看着什么实际发生,当你做一个本地图片搜索上。 浏览/选择图像后,你看到一些流量images.google.com/searchbyimage/upload
。 查看详细这项要求揭示的基本机制。
- 数据以格式发送
multipart/form-data
,你需要指定哪些字符串中的字符是区分不同领域(红色框)。 如果冰/谷歌周围,你会发现multipart/form-data
是某种形式的网络标准,但它其实并不重要,在这个例子中。 - 你需要(或者至少应该)包括原来的文件名(橙色框)。 也许这因素纳入搜索结果中。
- 充分,原始图像被包括在
encoded-image
场(绿色方框)。 - 该响应不包含实际的结果,它只是一个重定向到实际的结果页面(紫色框)
有几个字段这里没有显示,方式在底部。 他们不是超级有趣。
一旦我想通了基本的工作流程,它不仅是编码它的问题。 我只是复制我看到提琴手尽可能接近我可以在Web请求,使用标准的.NET Web请求的API。 对这些问题的答案这太问题表明你需要为了正确编码,并在Web请求发送主体数据的API。
从一些实验,我发现,你只需要两体场我包括在我的代码( encoded_image
和image_content
)。 通过Web UI将会包含更多,但显然他们不是必需的。
更多的试验表明,真正需要在没有显示提琴手其他标题或饼干。
对于我们而言,我们实际上并不想访问结果页面,只得到一个指向它。 因此,我们应该设置AllowAutoRedirect
至$false
。 这样一来,谷歌的302重定向直接提供给我们,我们可以从中提取结果页面的URL。
虽然写这篇编辑,我拍了拍我的额头,并意识到PowerShell的V3具有Invoke-WebRequest
cmdlet的,这有可能消除对.NET的Web API调用的需要。 不幸的是,我无法得到它的修修补补10分钟后正常工作,所以我放弃了。 好像有些问题与小命令编码数据,虽然我可能是错的方式。
function Get-GoogleImageSearchUrl
{
param(
[Parameter(Mandatory = $true)]
[ValidateScript({ Test-Path $_ })]
[string] $ImagePath
)
# extract the image file name, without path
$fileName = Split-Path $imagePath -Leaf
# the request body has some boilerplate before the raw image bytes (part1) and some after (part2)
# note that $filename is included in part1
$part1 = @"
--7dd2db3297c2202
Content-Disposition: form-data; name="encoded_image"; filename="$fileName"
Content-Type: application/octet-stream`r`n`r`n
"@
$part2 = @"
`r`n--7dd2db3297c2202--`r`n
"@
# grab the raw bytes composing the image file
$imageBytes = [Io.File]::ReadAllBytes($imagePath)
# the request body should sandwich the image bytes between the 2 boilerplate blocks
$encoding = New-Object Text.ASCIIEncoding
$data = $encoding.GetBytes($part1) + $imageBytes + $encoding.GetBytes($part2)
# create the HTTP request, populate headers
$request = [Net.HttpWebRequest] ([Net.HttpWebRequest]::Create('http://images.google.com/searchbyimage/upload'))
$request.Method = "POST"
$request.ContentType = 'multipart/form-data; boundary=7dd2db3297c2202' # must match the delimiter in the body, above
# don't automatically redirect to the results page, just take the response which points to it
$request.AllowAutoredirect = $false
# populate the request body
$stream = $request.GetRequestStream()
$stream.Write($data, 0, $data.Length)
$stream.Close()
# get response stream, which should contain a 302 redirect to the results page
$respStream = $request.GetResponse().GetResponseStream()
# pluck out the results page link that you would otherwise be redirected to
(New-Object Io.StreamReader $respStream).ReadToEnd() -match 'HREF\="([^"]+)"' | Out-Null
$matches[1]
}
$url = Get-GoogleImageSearchUrl 'C:\somepic.jpg'
Start-Process $url