65.9K
CodeProject 正在变化。 阅读更多。
Home

Google 图片搜索 API

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (73投票s)

2005年10月5日

CPOL

11分钟阅读

viewsIcon

453099

downloadIcon

10031

以编程方式查询Google图片。

引言

在我撰写论文的研究过程中,我需要针对最流行的搜索引擎进行大量的图片搜索查询。Yahoo! 提供了一个 Yahoo! SDK API,也支持图片搜索,对我很有帮助。然而,Google 出于一些晦涩的原因,只提供了 常规搜索的API,而没有提供图片搜索的API。几周前,我偶然看到了 Peter Bromberg 实现的一个非常简单的Google网页翻译服务。于是我想,为什么不为Google图片搜索做类似的事情呢?是的,我做到了,就是这个。使用的正则表达式比翻译服务中使用的要复杂得多,但最终,它们基本上是相同的。

注意:本文已翻译成中文,翻译版本可在此 查看

源文件包含什么?

源文件包含两个项目。Ilan.Google.API项目包含一个DLL,可用于以编程方式查询Google图片搜索。Ilan.Test.Google.API项目包含一个简单的应用程序,允许您运行查询并动态显示表单上的所有结果图片。双击缩略图将显示完整的原始图像。此应用程序旨在展示API的易用性。我不建议将其作为真正的搜索工具(至少目前是这样),因为

  1. 它在一个单独的线程中获取所有图片(缩略图)。尽管它提供了在所有缩略图下载完成之前查看完整图片的功能,但一个“真正的”应用程序需要同时下载多个缩略图,从而大大提高性能。
  2. 仅支持简单的查询(空格分隔的单词)。不处理特殊字符。如果您需要支持更复杂的查询,则必须解析查询并将其转换为符合URL格式的内容。

快速入门 - 如何使用API?

如果您不关心它的工作原理,只想使用该库,那么这一部分就是为您准备的 :-)

  • 在您的项目中添加对Ilan.Google.API库的引用。
  • 添加 using 指令
    using Ilan.Google.API.ImageSearch;
  • 当您需要运行查询时,请确保它符合Google支持的URL格式。为此,我建议您在Google图片搜索上检查查询,并查看他们如何构建URL。例如,如果您只需要支持空格分隔的单词的简单查询,您只需将查询转换为由加号(+)分隔的单词列表。例如,查询“apple cake”必须转换为“apple+cake”。请注意,几个空格字符必须转换为单个+号,因此我不建议简单地调用string.Replace。您可以使用我在演示项目中使用的正则表达式。
    string formattedQuery = 
        Regex.Replace(nonFormattedQuery, @"\s{1,}", "+");
  • 要运行查询(例如,获取前50个结果),请使用SearchService.SearchImages方法。
    SearchResponse response = 
       SearchService.SearchImages(formattedQuery, 1, 50, true);
  • response对象保存了给定查询的所有前50个结果(如果没有更多结果,则少于50个)。例如,您可以通过response.Results数组检索第一个图片的URL。
    string firstImageUrl = response.Results[0].ImageUrl;
  • SearchService.SearchImages方法的参数为:
    • (string) query - 要发送的查询。
    • (int) startPosition - 要检索的第一个项目的索引(必须为正数)。
    • (int) resultsRequested - 要检索的结果数(必须在1到(1000 - startPosition)之间)。
    • (bool) filterSimilarResults - 设置为'true'以自动省略相似条目。设置为'false'以检索所有匹配的图片。
    • [可选: (SafeSearchFiltering) safeSearch - 指示要使用的safeSearch级别。]
  • 好吧,我想就这些了。请记住,Google不会返回前1000个结果以外的结果,所以如果您试图获取超过前1000个结果,我将抛出异常……

如果您想知道原因和工作原理……

……那么我希望这一部分能帮到您。

返回的对象

SearchResponseSearchResult类非常直观。一个查询返回一个SearchReponse,其中包含查询的总可用结果数以及一个SearchResult对象数组,每个对象代表Google返回的一个单独的图片。SearchResult对象包含图片的缩略图URL(位于Google的某个地方)以及实际图片的URL(在其来源处)。

构建查询URL

通过使用 Google图片搜索 发送几个查询后,事实证明,您可以执行简单的查询“apple cake” 使用此URL

进一步挖掘,您可以通过添加“&start=”来获取特定位置的结果。因此,如果您想获取从第21到第40个结果(即,如果您使用他们的网站,那就是第二页),URL应该是 这个

请注意,图片的索引是从0开始的,所以要从第21个结果开始,您必须指定“&start=20”。然后,我发现有一个默认过滤器会省略与前一个结果相似的结果。如果您想禁用此过滤器,则需要添加“&filter=0”。快速测试将显示“&filter=1”会开启该过滤器。为了看到过滤器的效果,我建议您运行以下两个查询,它们返回从第900个结果开始的结果:

最后,pedrito68告诉我,您还可以通过添加“&safe=...”来选择SafeSearch模式。Google的SafeSearch会阻止包含露骨性内容的网页出现在搜索结果中。有三个选项:“active”(过滤露骨文本和露骨图片),“moderate”(仅过滤露骨图片 - 默认行为)和“off”(不过滤搜索结果)。

我尝试找出一种方法来定义返回结果的数量,但没有成功。我每次仍然得到20个结果。更多信息稍后……

所以,总结查询部分,给定查询、起始位置和过滤器,构建查询URL可以这样做:

string requestUrl = 
  string.Format("http://images.google.com/images?" + 
   "q={0}&start={1}&filter={2}&safe={3}", 
   query, startPosition.ToString(), 
   (filterSimilarResults)?1.ToString():0.ToString(), 
   SafeSearchFiltering.Moderate );

发送查询并检索结果

发送查询并检索返回的HTML文件非常简单,而且非常普遍。

HttpWebRequest request = 
    (HttpWebRequest)WebRequest.Create(requestUrl);
string resultPage = string.Empty;
using (HttpWebResponse httpWebResponse = 
           (HttpWebResponse)request.GetResponse())
{
    using (Stream responseStream = 
              httpWebResponse.GetResponseStream())
    {
        using (StreamReader reader = 
                 new StreamReader(responseStream))
        {
            resultPage = reader.ReadToEnd();
        }
    }
}

从检索到的HTML中提取信息

这是令人头疼的部分。我们必须解析HTML并提取查询的总可用结果数以及每个检索到的图片的具体信息。在分析了从Google获得的HTML后,我设法找到一个重复的模式,可以准确地知道这些感兴趣的信息位在HTML中的位置。不用说,如果Google更改返回HTML的格式,解析将失败! 当然,我依赖正则表达式来解析文本。以下是API中使用的不同模式:

[编辑注释:使用换行符以避免滚动。]

1. Regex imagesRegex = new Regex(@"(\x3Ca\s+href=/imgres\" + 
                       @"x3Fimgurl=)(?<imgurl>http" + 
                       @"[^&>]*)([>&]{1})" + 
                       @"([^>]*)(>{1})(<img\ssrc\" + 
                       @"x3D)(""{0,1})(?<images>/images" + 
                       @"[^""\s>]*)([\s])+(width=)" + 
                       @"(?<width>[0-9,]*)\s+(height=)" + 
                       @"(?<height>[0-9,]*)");

此模式用于检索每张图片的详细信息。原始图片URL捕获到“imgurl”组中,缩略图URL捕获到“images”组中,缩略图的宽度和高度分别捕获到“width”和“height”组中。

[编辑注释:使用换行符以避免滚动。]

2. Regex dataRegex = new Regex(@"([^>]*)(>)\s{0,1}(<br>){0,1}\s{0,1}" + 
                     @"(?<width>[0-9,]*)\s+x\s+(?<height>[0-9,]*)" + 
                     @"\s+pixels\s+-\s+(?<size>[0-9,]*)(k)");

此模式用于检索每张图片的额外信息 - 原始图片的宽度、高度和大小(分别在“width”、“height”和“size”组中)。我没有找到一种方法将相同的模式用于所有图片的详细信息 - 我猜有,但我搜索了一段时间后就放弃了……

[编辑注释:使用换行符以避免滚动。]

3. Regex totalResultsRegex = new Regex(@"(?<lastResult>" + 
                             @"[0-9,]*)(\s*</b>\s*)(of(\s)" +
                             @"+(about){0,1}(\s*<b>\s*)" + 
                             @"(?<totalResultsAvailable>[0-9,]*)");

此模式用于检索查询的总可用结果数(可以在查询结果的HTML右上角找到)。我还提取了最后一个结果索引 - 以便找到没有更多结果的时间。

由于我不是正则表达式专家,如果您想获得更多相关信息并更好地理解模式的工作原理,我建议阅读以下内容: Regex Language Reference Introduction to Regular Expressions,当然您必须查看 The Regulator

每查询20个结果怎么办?

很简单。一旦您知道URL的“start=”部分,您就可以在循环中运行查询,直到达到所需的结果数。

以及1000个结果的限制?

嗯,抱歉。我找不到绕过它的方法。不过,我假设在几乎所有的应用程序中,1000个结果应该足够了。此外,一旦您获得最后一个结果,其中大多数对实际查询来说已经完全不相关了……

感谢和道歉

我想感谢 Roy Osherove 和他的 Regulator。我过去曾几次使用过正则表达式,但大多是使用非常简单的模式。这里使用的表达式是我写过的最复杂的,如果没有“The Regulator”的帮助,我将无法对其进行测试并成功编写。这让我想到道歉 - 我使用的模式很可能可以简化。如果您找到了简化它的方法(且性能没有下降),请告诉我,我会更新代码。最后,我想感谢“pedrito68”,他根据此API的第一个版本为我提供了非常有用的评论(和代码),我已将其添加到当前版本中(请参阅历史记录部分)。

结论

Google图片搜索API本质上是一个工具,如果您需要以编程方式对Google进行图片搜索,就可以使用它。由于它解析Google返回的HTML,如果此HTML的格式发生变化,库的实现也必须相应地进行更改。实现非常简单。它展示了一个如何将URL发送到Web服务器(使用HttpWebRequest对象)并检索Web服务器返回的HTML的简单示例。它还使用正则表达式(使用System.Text.RegularExpressions.Regex类)以及一些相当复杂的模式来从HTML中提取相关数据。最后,演示应用程序展示了如何使用该API。

个人而言 - 在过去几天里,我使用此API运行了超过40,000个单字查询。它已被证明非常准确,并且正则表达式从未出现过故障。一个非常有趣的特点是,它不像常规SDK那样有数量限制。例如,Google的网络搜索API不允许您在一天(24小时)内使用同一个密钥运行超过1000个查询。同样,Yahoo!每天有5000个查询的限制。可能需要将此API改编为提供常规搜索功能,并绕过Google每天1000个查询的限制,或者将其改编为Yahoo!并绕过他们的限制……

如果您觉得这篇文章对您有帮助,请不要忘记投票。我希望它能尽快摆脱“未编辑”部分。此外,欢迎您访问我的 博客

历史

  • 2005年10月5日 - 第一个版本。
  • 2005年10月9日 - 添加了pedrito68推荐的更改和一些错误修复
    • 提取每张图片的更多详细信息:文件大小/宽度/高度/名称/扩展名,缩略图宽度/高度。
    • 在单独的线程上获取缩略图。
    • 双击缩略图弹出完整图片。
    • 支持SafeSearch
    • 错误修复 - 当查询只有少量结果而请求更多结果时,我们会多次获得相同的结果。例如,如果一个查询只返回三张图片,而我们请求100张,那么我们将获得15个结果(相同的3张图片重复5次)。
  • 2006年1月4日 – 由于Google返回的HTML格式发生变化,更新了第二个正则表达式。
  • 2006年12月27日 – 更新了源代码
    • 在.NET 2.0下运行,而不是.NET 1.1(相应地,VS2005也一样)。
    • API使用的三个正则表达式现在从外部文本文件中加载,其名称从配置文件中读取。所以现在,您可以更改正则表达式而无需重新编译甚至重新运行应用程序,只需更新文本文件中的regex即可。要重新加载正则表达式,请调用新的SearchService.LoadRegexStrings()函数。我在示例应用程序中添加了一个执行此操作的按钮,因此很容易看到它是如何工作的。我将regex放在文本文件中,而不是直接放在配置文件中,以便简化regex,并且不必使其更复杂以符合XML格式。
  • 2007年1月28日 - 更新了源代码。
    • 支持Google图片搜索返回的新格式结果。
    • 缩略图在单独的线程上下载(测试应用程序)。
    • 更好的UI线程处理(测试应用程序)。
  • 2007年3月11日
    • 更新以符合Google图片搜索返回的新格式结果。
© . All rights reserved.