1

The following Powershell script runs a Google search of an image stored within my hard drive.

How can I get the link which is followed to get to the results page? Is it possible to navigate to the different webpages displayed on it?

I've tried $request.Links | Select href to try and get a list of the links, but it didn't work. I've also tried to add Write-Output $respStream to the code, but then it doesn't run.

Set-ExecutionPolicy Bypass -scope Process -Force

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:\Users\Path\filename.jpeg"

Start-Process $url
2
  • 1
    Are you trying to get the URL that the 302 redirects to? If so, read the response's Location header instead. Commented Dec 13, 2019 at 19:28
  • 1
    Why are you using [Net.HttpWebRequest] to make the web request instead of using Invoke-WebRequest? This does not necessarily solve your problem but can guide you in the right direction Commented Dec 13, 2019 at 19:44

1 Answer 1

3
+150

As mentioned by @soc, you shouldn't need the stream to pull the url, the moved to location is in the response header:

    $request = [Net.HttpWebRequest] ([Net.HttpWebRequest]::Create('http://images.google.com/searchbyimage/upload'))
    $request.AllowAutoredirect = $false
    ...
    $response = $request.GetResponse()
    if ($response.StatusCode -eq 302) {
        $redirect_url = $response.Headers["Location"]
        write-host $redirect_url
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.