Google 图片搜索 API






4.86/5 (73投票s)
以编程方式查询Google图片。
引言
在我撰写论文的研究过程中,我需要针对最流行的搜索引擎进行大量的图片搜索查询。Yahoo! 提供了一个 Yahoo! SDK API,也支持图片搜索,对我很有帮助。然而,Google 出于一些晦涩的原因,只提供了 常规搜索的API,而没有提供图片搜索的API。几周前,我偶然看到了 Peter Bromberg 实现的一个非常简单的Google网页翻译服务。于是我想,为什么不为Google图片搜索做类似的事情呢?是的,我做到了,就是这个。使用的正则表达式比翻译服务中使用的要复杂得多,但最终,它们基本上是相同的。
注意:本文已翻译成中文,翻译版本可在此 查看。
源文件包含什么?
源文件包含两个项目。Ilan.Google.API项目包含一个DLL,可用于以编程方式查询Google图片搜索。Ilan.Test.Google.API项目包含一个简单的应用程序,允许您运行查询并动态显示表单上的所有结果图片。双击缩略图将显示完整的原始图像。此应用程序旨在展示API的易用性。我不建议将其作为真正的搜索工具(至少目前是这样),因为
- 它在一个单独的线程中获取所有图片(缩略图)。尽管它提供了在所有缩略图下载完成之前查看完整图片的功能,但一个“真正的”应用程序需要同时下载多个缩略图,从而大大提高性能。
- 仅支持简单的查询(空格分隔的单词)。不处理特殊字符。如果您需要支持更复杂的查询,则必须解析查询并将其转换为符合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个结果,我将抛出异常……
如果您想知道原因和工作原理……
……那么我希望这一部分能帮到您。
返回的对象
SearchResponse
和SearchResult
类非常直观。一个查询返回一个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个结果开始的结果:
- http://images.google.com/images?q=apple+cake&start=900&filter=0
- http://images.google.com/images?q=apple+cake&start=900&filter=1
最后,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图片搜索返回的新格式结果。