-->

脚本使用谷歌图片搜索本地图像作为输入(Script to use Google Image Sear

2019-07-19 02:03发布

我在寻找一个批处理或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,然后点击它们编程来选择本地文件。 但在这里我没有足够的经验来实现这一目标。

Answer 1:

酷的问题! 我花了太多的时间与此修补,但我认为终于得到它:)

概括地说,你要上传图片的原始字节,嵌入式和一些其他的东西沿着正确的格式,以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 。 查看详细这项要求揭示的基本机制。

  1. 数据以格式发送multipart/form-data ,你需要指定哪些字符串中的字符是区分不同领域(红色框)。 如果冰/谷歌周围,你会发现multipart/form-data是某种形式的网络标准,但它其实并不重要,在这个例子中。
  2. 你需要(或者至少应该)包括原来的文件名(橙色框)。 也许这因素纳入搜索结果中。
  3. 充分,原始图像被包括在encoded-image场(绿色方框)。
  4. 该响应不包含实际的结果,它只是一个重定向到实际的结果页面(紫色框)

有几个字段这里没有显示,方式在底部。 他们不是超级有趣。

一旦我想通了基本的工作流程,它不仅是编码它的问题。 我只是复制我看到提琴手尽可能接近我可以在Web请求,使用标准的.NET Web请求的API。 对这些问题的答案这太问题表明你需要为了正确编码,并在Web请求发送主体数据的API。

从一些实验,我发现,你只需要两体场我包括在我的代码( encoded_imageimage_content )。 通过Web UI将会包含更多,但显然他们不是必需的。

更多的试验表明,真正需要在没有显示提琴手其他标题或饼干。

对于我们而言,我们实际上并不想访问结果页面,只得到一个指向它。 因此,我们应该设置AllowAutoRedirect$false 。 这样一来,谷歌的302重定向直接提供给我们,我们可以从中提取结果页面的URL。

虽然写这篇编辑,我拍了拍我的额头,并意识到PowerShell的V3具有Invoke-WebRequest cmdlet的,这有可能消除对.NET的Web API调用的需要。 不幸的是,我无法得到它的修修补补10分钟后正常工作,所以我放弃了。 好像有些问题与小命令编码数据,虽然我可能是错的方式。



Answer 2:

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


文章来源: Script to use Google Image Search with local image as input