3

我想以编程方式查找给定图像 URL 的类似图像的 URL 列表。我找不到任何免费的图片搜索 API,所以我试图通过抓取 Google 的Search by Image来做到这一点。

如果我有图片 URL,请说http://i.imgur.com/oLmwq.png,然后导航到https://www.google.com/searchbyimage?&image_url=http://i.imgur.com/oLmwq .png提供相关的图像和信息。

如何jsdom.env生成浏览器从上述 URL 获取的 HTML?

这是我尝试过的(CoffeeScript):

jsdom = require 'jsdom'
url = 'https://www.google.com/searchbyimage?&image_url=http://i.imgur.com/oLmwq.png'
jsdom.env
    html: url
    scripts: [ "http://code.jquery.com/jquery.js" ]
    features:
        FetchExternalResources: ['script']
        ProcessExternalResources: ['script']
    done: (errors, window) ->
        console.log window.$('body').html()

您可以看到 HTML 与我们想​​要的不匹配。这是 Jsdom 的 HTTP 标头的问题吗?

4

2 回答 2

4

对于这样的任务,我发现request + Cheerio比 jsdom 更容易。我看到您已经找到了答案,但我想我会提到它作为替代解决方案。

例子:

var request = require('request'),
    cheerio = require('cheerio');

var google = 'https://www.google.com/searchbyimage';
var image = 'http://i.imgur.com/oLmwq.png';

var options = {
  url: google,
  qs: { image_url: image },
  headers: { 'user-agent': 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11' }
};

request(options, function (err, res, body) {
  var $ = cheerio.load(body);
  …
});
于 2013-01-26T00:19:41.180 回答
2

问题是 Jsdom 的 User-Agent HTTP 标头。一旦设置好一切(几乎)工作:

jsdom = require 'jsdom'
url = 'https://www.google.com/searchbyimage?&image_url=http://i.imgur.com/oLmwq.png'
jsdom.env
    html: url
    headers:
        'User-Agent': 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'
    scripts: [ "http://code.jquery.com/jquery.js" ]
    features:
        FetchExternalResources: ['script']
        ProcessExternalResources: ['script']

    done: (errors, window) ->
        $ = window.$
        $('#iur img').parent().each (index, elem) ->
            href = $(elem).attr 'href'
            url = href.split('?')[1].split('&')[0].split('=')[1]
            console.log url

这给了我们一个很好的视觉相似图像列表。现在唯一的问题是 Jsdom 返回结果后会抛出错误:

timers.js:103
            if (!process.listeners('uncaughtException').length) throw e;
                                                                      ^
TypeError: Cannot call method 'call' of undefined
    at new <anonymous> (/project-root/node_modules/jsdom/lib/jsdom/browser/index.js:54:13)
    at _.Zl (https://www.google.com/xjs/_/js/s/c,sb,cr,cdos,jsa,ssb,sf,tbpr,tbui,rsn,qi,ob,mb,lc,hv,cfm,klc,kat,aut,esp,bihu,amcl,kp,lu,m,rtis,shb,sfa,hsm,pcc,csi/rt=j/ver=3w99aWPP0po.en_US./d=1/sv=1/rs=AItRSTPrAylXrfkOPyRRY-YioThBMqxW2A:1238:93)
    at _.jm (https://www.google.com/xjs/_/js/s/c,sb,cr,cdos,jsa,ssb,sf,tbpr,tbui,rsn,qi,ob,mb,lc,hv,cfm,klc,kat,aut,esp,bihu,amcl,kp,lu,m,rtis,shb,sfa,hsm,pcc,csi/rt=j/ver=3w99aWPP0po.en_US./d=1/sv=1/rs=AItRSTPrAylXrfkOPyRRY-YioThBMqxW2A:1239:399)
    at _.km (https://www.google.com/xjs/_/js/s/c,sb,cr,cdos,jsa,ssb,sf,tbpr,tbui,rsn,qi,ob,mb,lc,hv,cfm,klc,kat,aut,esp,bihu,amcl,kp,lu,m,rtis,shb,sfa,hsm,pcc,csi/rt=j/ver=3w99aWPP0po.en_US./d=1/sv=1/rs=AItRSTPrAylXrfkOPyRRY-YioThBMqxW2A:1241:146)
    at Object._onTimeout (https://www.google.com/xjs/_/js/s/c,sb,cr,cdos,jsa,ssb,sf,tbpr,tbui,rsn,qi,ob,mb,lc,hv,cfm,klc,kat,aut,esp,bihu,amcl,kp,lu,m,rtis,shb,sfa,hsm,pcc,csi/rt=j/ver=3w99aWPP0po.en_US./d=1/sv=1/rs=AItRSTPrAylXrfkOPyRRY-YioThBMqxW2A:1248:727)
    at Timer.list.ontimeout (timers.js:101:19)
于 2012-12-22T14:14:06.410 回答