powershell - 使用本 map 片作为输入使用 Google 图片搜索的脚本

标签 powershell curl batch-file google-image-search

我正在寻找批处理或 Powershell 脚本,以使用本地镜像作为输入在 Google 图像上搜索类似图像。

enter image description here

我目前的研究

使用 URL 而不是本地文件进行图像搜索的语法如下:https://www.google.com/searchbyimage?image_url=TEST其中 TEST 可以替换为您拥有的任何图像 URL。

我玩过 cURL for windowsimgur作为临时图像保护程序。
我能够通过批处理将文件上传到imgur。然后使用图像 URL 在 Google 上搜索类似的图像。

但我想知道是否可以不使用任何临时缓存(如 imgur 或任何其他在线图片服务)。只是一批, curl ,谷歌和我。

只是一个想法。 VBS 脚本是否能够使用本地文件作为输入在 Google 图片上进行搜索?
或者是类似的网络服务,如 Tineye更适合那个任务?

此 powershell 代码段将打开 Google 的图片搜索。

$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 会将您发送到实际结果页面。

此函数将返回结果页面 URL。你可以用它做任何你想做的事情,但只需在浏览器中打开结果,将它传递给 Start-Process .

当然,Google 可以随时为此更改工作流程,因此不要指望此脚本永远有效。

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

编辑/解释

这里有一些更详细的信息。我基本上只是带你完成我在弄清楚这一点时采取的步骤。

首先,我只是继续进行本地镜像搜索。

Google image search

它发送给您的 URL 很长(在 longcat 的情况下约为 1500 个字符),但长度不足以完全编码图像 (60KB)。因此,您可以立即看出它比简单地执行诸如 base64 编码之类的操作更复杂。

接下来,我启动了 Fiddler 并查看了进行本地镜像搜索时实际发生的情况。浏览/选择图片后,您会看到一些流量到 images.google.com/searchbyimage/upload .详细查看该请求揭示了基 native 制。

Fiddler session
  • 正在以 multipart/form-data 格式发送数据,并且您需要指定分隔不同字段(红色框)的字符串。如果你在 Bing/Google 周围,你会发现 multipart/form-data是某种网络标准,但对于这个例子来说真的无关紧要。
  • 您需要(或至少应该)包含原始文件名(橙色框)。也许这会影响搜索结果。
  • 完整的原始图像包含在 encoded-image 中字段(绿色框)。
  • 响应不包含实际结果,只是重定向到实际结果页面(紫色框)

  • 此处未显示一些字段,位于底部。他们不是 super 有趣。

    一旦我弄清楚了基本的工作流程,就只需要编写代码了。我只是使用标准的 .NET Web 请求 API 尽可能地复制了我在 Fiddler 中看到的 Web 请求。 this SO question的答案演示您需要的 API,以便在 Web 请求中正确编码和发送正文数据。

    通过一些实验,我发现您只需要我在代码中包含的两个正文字段( encoded_imageimage_content )。浏览 Web UI 包括更多内容,但显然它们不是必需的。

    更多的实验表明 Fiddler 中显示的其他标题或 cookie 都不是真正需要的。

    出于我们的目的,我们实际上并不想访问结果页面,而只是获取指向它的指针。因此我们应该设置 AllowAutoRedirect$false .这样,Google 的 302 重定向就会直接提供给我们,我们可以从中提取结果页面 URL。

    在编写此编辑时,我拍了拍额头并意识到 Powershell v3 具有 Invoke-WebRequest cmdlet,这可能会消除对 .NET Web API 调用的需要。不幸的是,我在修修补补 10 分钟后无法使其正常工作,所以我放弃了。 cmdlet 对数据进行编码的方式似乎有些问题,尽管我可能是错的。

    关于powershell - 使用本 map 片作为输入使用 Google 图片搜索的脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14634321/

    相关文章:

    powershell - 使用Powershell转换CSV文件

    php - 如何越来越多地显示数据库结果?

    curl - Mattermost(团队聊天)- 如何通过 curl 发布到 channel ?

    ruby - 如何使用 httparty 模仿 curl Action

    powershell - Powershell/批处理网络映射驱动器

    powershell - 批处理脚本可以知道它是否是从 PowerShell 调用的吗?

    batch-file - 在批处理文件 START 命令中转义逗号?

    powershell - 解析大型文本文件最终导致内存和性能问题

    .net - Powershell、JSON 和 UTF8 有 cyrrylic 问题

    arrays - 连接字符数组元素