从 Google 选择并下载随机图片

Posted

技术标签:

【中文标题】从 Google 选择并下载随机图片【英文标题】:Select and Download random image from Google 【发布时间】:2015-03-06 22:25:27 【问题描述】:

是否有任何示例如何从谷歌搜索和下载随机图像?使用随机搜索字符串?

我想将此图像用作隐写图像,并且我希望它是随机的。

我在 Visual Studio 2012 中使用 C#。

【问题讨论】:

你真的想要一个随机搜索字符串吗?例如HE8IHN96HV3?这很可能不会从 Google 图片返回任何匹配项。相反,您可以从字典中选择一个随机单词,进行搜索,然后从所有结果中选择一个随机图像。为了在 C# 中实际实现这一点,请查看位于 googledotnet.codeplex.com 的 Google 搜索 API 文档 谢谢卡尼瓦鲁斯。我会检查的。 我只能看到提出一些……嗯……“有趣”的结果,我不会把它放到业务应用程序中。 :-P 【参考方案1】:

您可能不想要随机搜索字符串。您可能想要随机主题。这里有一些代码可以帮助你。首先,创建一个主题列表:

private readonly List<string> _topics = new List<string> "dog", "car", "truck", "cat", "florida";

当然,您可以随意更改、添加和删除任意数量的主题。接下来,我们将创建一个函数来从 Google 图片搜索中检索 html 代码,随机选择我们的一个主题进行搜索:

private string GetHtmlCode()

    var rnd = new Random();

    int topic = rnd.Next(0, _topics.Count - 1);

    string url = "https://www.google.com/search?q=" + _topics[topic] + "&tbm=isch";
    string data = "";

    var request = (HttpWebRequest)WebRequest.Create(url);
    var response = (HttpWebResponse)request.GetResponse();

    using (Stream dataStream = response.GetResponseStream())
    
        if (dataStream == null)
            return "";
        using (var sr = new StreamReader(dataStream))
        
            data = sr.ReadToEnd();
        
    
    return data;

一旦我们有了 HTML 代码,我们需要解析出位于 images_table 表下方的 img 标记,并将图像的 URL 存储在一个列表中:

private List<string> GetUrls(string html)

    var urls = new List<string>();
    int ndx = html.IndexOf("class=\"images_table\"", StringComparison.Ordinal);
    ndx = html.IndexOf("<img", ndx, StringComparison.Ordinal);

    while (ndx >= 0)
    
        ndx = html.IndexOf("src=\"", ndx, StringComparison.Ordinal);
        ndx = ndx + 5;
        int ndx2 = html.IndexOf("\"", ndx, StringComparison.Ordinal);
        string url = html.Substring(ndx, ndx2 - ndx);
        urls.Add(url);
        ndx = html.IndexOf("<img", ndx, StringComparison.Ordinal);
    
    return urls;

我们需要的最后一个函数是获取一个 URL 并将图像字节下载到一个字节数组中:

private byte[] GetImage(string url)

    var request = (HttpWebRequest)WebRequest.Create(url);
    var response = (HttpWebResponse)request.GetResponse();

    using (Stream dataStream = response.GetResponseStream())
    
        if (dataStream == null)
            return null;
        using (var sr = new BinaryReader(dataStream))
        
            byte[] bytes = sr.ReadBytes(100000);

            return bytes;
        
    

    return null;

最后,我们只需要将它们捆绑在一起:

string html = GetHtmlCode();
List<string> urls = GetUrls(html);
var rnd = new Random();

int randomUrl = rnd.Next(0, urls.Count - 1);

string luckyUrl = urls[randomUrl];

byte[] image = GetImage(luckyUrl);
using (var ms = new MemoryStream(image))

    pictureBox1.Image = Image.FromStream(ms);


更新

我收到了一些关于此答案的请求,要求我对其进行修改,以便加载实际的全尺寸图像而不是缩略图。我已经修改了我的原始代码,以便它现在加载全尺寸图像而不是缩略图。

首先,像以前一样,创建一个主题列表:

private readonly List<string> _topics = new List<string>  "dog", "car", "truck", "cat", "florida" ;

当然,您可以随意更改、添加和删除任意数量的主题。接下来,我们将创建一个函数来从 Google 图片搜索中检索 HTML 代码,随机选择我们的一个主题进行搜索。这里的GetHtmlCode() 与缩略图版本中的GetHtmlCode() 不同,我们必须在请求中添加AcceptUserAgent,否则Google 不会向我们提供完整尺寸的图片网址:

private string GetHtmlCode()

    var rnd = new Random();

    int topic = rnd.Next(0, _topics.Count - 1);

    string url = "https://www.google.com/search?q=" + _topics[topic] + "&tbm=isch";
    string data = "";

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Accept = "text/html, application/xhtml+xml, */*";
    request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";

    var response = (HttpWebResponse)request.GetResponse();

    using (Stream dataStream = response.GetResponseStream())
    
        if (dataStream == null)
            return "";
        using (var sr = new StreamReader(dataStream))
        
            data = sr.ReadToEnd();
        
    
    return data;

GetUrls() 方法也被重写,因为我们现在返回的 HTML 代码与我们在“缩略图”版本中返回的 HTML 代码不同。它仍然从 HTML 代码中解析出 URL:

private List<string> GetUrls(string html)

    var urls = new List<string>();

    int ndx = html.IndexOf("\"ou\"", StringComparison.Ordinal);

    while (ndx >= 0)
    
        ndx = html.IndexOf("\"", ndx + 4, StringComparison.Ordinal);
        ndx++;
        int ndx2 = html.IndexOf("\"", ndx, StringComparison.Ordinal);
        string url = html.Substring(ndx, ndx2 - ndx);
        urls.Add(url);
        ndx = html.IndexOf("\"ou\"", ndx2, StringComparison.Ordinal);
    
    return urls;

我们需要的最后一个函数是获取一个 URL 并将图像字节下载到一个字节数组中。此功能只有一个与“缩略图”版本不同的细微变化。我们不得不更改ReadBytes() 中的数字,因为我们的图片现在会更大:

private byte[] GetImage(string url)

    var request = (HttpWebRequest)WebRequest.Create(url);
    var response = (HttpWebResponse)request.GetResponse();

    using (Stream dataStream = response.GetResponseStream())
    
        if (dataStream == null)
            return null;
        using (var sr = new BinaryReader(dataStream))
        
            byte[] bytes = sr.ReadBytes(100000000);

            return bytes;
        
    

    return null;

最后,我们只需要像以前一样将它们捆绑在一起:

string html = GetHtmlCode();
List<string> urls = GetUrls(html);
var rnd = new Random();

int randomUrl = rnd.Next(0, urls.Count - 1);

string luckyUrl = urls[randomUrl];

byte[] image = GetImage(luckyUrl);
using (var ms = new MemoryStream(image))

    pictureBox1.Image = Image.FromStream(ms);

【讨论】:

@mafu - 我同意!哈哈 这很酷。如果可以下载单击缩略图时获得的全质量图像会更好。 有没有办法用全质量图像做到这一点?小的很小,几乎看不见。 @Julien - 我编辑了我的答案以提供该功能。 @MadBoy - 我编辑了我的答案以提供该功能。【参考方案2】:

Icemanind 的回答主要对我有用,尽管我不得不重写 Geturls:

    private List<string> GetUrls(string html)
    
        var urls = new List<string>();

        string search = @",""ou"":""(.*?)"",";
        MatchCollection matches = Regex.Matches(html, search);

        foreach (Match match in matches)
        
            urls.Add(match.Groups[1].Value);
        

        return urls;
    

我还必须找到 Image.FromStream (source) 的 WPF 替代方案:

            byte[] image = GetImage(luckyUrl);

            using (var stream = new MemoryStream(image))
            
                var bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.StreamSource = stream;
                bitmap.CacheOption = BitmapCacheOption.OnLoad;
                bitmap.EndInit();
                bitmap.Freeze();

                this.img.Source = bitmap;
            

【讨论】:

以上是关于从 Google 选择并下载随机图片的主要内容,如果未能解决你的问题,请参考以下文章

如何把Google earth里的地图导入ARCGIS??

google 为啥android 全盘加密

使用 REST api 从 Google Drive 下载图片

从Google搜索中获取某些图片的网址

使用 Google Firebase 同时上传多张图片

如何从Google表格下载具有特定边距和分页符的PDF文件?