如何从 response.body 获取节点中 '<img src=''>' 的绝对路径

Posted

技术标签:

【中文标题】如何从 response.body 获取节点中 \'<img src=\'\'>\' 的绝对路径【英文标题】:How do I get the absolute path for '<img src=''>' in node from the a response.body如何从 response.body 获取节点中 '<img src=''>' 的绝对路径 【发布时间】:2016-10-10 13:45:50 【问题描述】:

所以我想使用 request-promise 来拉取页面的正文。一旦我有了页面,我想收集所有标签并获取这些图像的 src 数组。假设页面上的 src 属性同时具有相对路径和绝对路径。我想要一个页面上 imgs 的绝对路径数组。我知道我可以使用一些字符串操作和 npm 路径来构建绝对路径,但我想找到一种更好的方法。

var rp = require('request-promise'),
    cheerio = require('cheerio');

var options = 
    uri: 'http://www.google.com',
    method: 'GET',
    resolveWithFullResponse: true
;

rp(options)
  .then (function (response) 
    $ = cheerio.load(response.body);
    var relativeLinks = $("img");
    relativeLinks.each( function() 
        var link = $(this).attr('src');
        console.log(link);
        if (link.startsWith('http'))
            console.log('abs');
        
        else 
            console.log('rel');
        
   );
);

结果

  /logos/doodles/2016/phoebe-snetsingers-85th-birthday-5179281716019200-hp.gif
  rel

【问题讨论】:

getting the absolute path of a <img/>的可能重复 @Midas 这个问题与其他问题密切相关,但由于在这种情况下 DOM 和 jQuery 以及在这种情况下 Cheerio 之间的实现差异,这个问题并不完全重复。执行 $(this) 或 $('img')[0].src 之类的操作不会在 Cheerio 中返回任何内容。 【参考方案1】:

将您的页面 URL 存储为变量,使用 url.resolve 将各个部分连接在一起。在 Node REPL 中,这适用于相对路径和绝对路径(因此称为“解析”):

$:~/Projects/test$ node
> var base = "https://www.google.com";
undefined
> var imageSrc = "/logos/doodles/2016/phoebe-snetsingers-85th-birthday-5179281716019200-hp.gif";
undefined
> var url = require('url');
undefined
> url.resolve(base, imageSrc);
'https://www.google.com/logos/doodles/2016/phoebe-snetsingers-85th-birthday-5179281716019200-hp.gif'
> imageSrc = base + imageSrc;
'https://www.google.com/logos/doodles/2016/phoebe-snetsingers-85th-birthday-5179281716019200-hp.gif'
> url.resolve(base, imageSrc);
'https://www.google.com/logos/doodles/2016/phoebe-snetsingers-85th-birthday-5179281716019200-hp.gif'

您的代码将更改为:

var rp = require('request-promise'),
    cheerio = require('cheerio'),
    url = require('url'),
    base = 'http://www.google.com';

var options = 
    uri: base,
    method: 'GET',
    resolveWithFullResponse: true
;

rp(options)
  .then (function (response) 
    $ = cheerio.load(response.body);
    var relativeLinks = $("img");
    relativeLinks.each( function() 
        var link = $(this).attr('src');
        var fullImagePath = url.resolve(base, link); // should be absolute 
        console.log(link);
        if (link.startsWith('http'))
            console.log('abs');
        
        else 
            console.log('rel');
        
   );
);

【讨论】:

【参考方案2】:

要在您的场景中获取图像链接数组,您可以使用url.resolveimg 标记的相对src 属性与请求URL 解析,从而生成绝对URL。数组传递给最终的then;如果需要,您可以对数组执行 console.log 以外的其他操作。

var rp = require('request-promise'),
    cheerio = require('cheerio'),
    url = require('url'),
    base = 'http://www.google.com';

var options = 
    uri: base,
    method: 'GET',
    resolveWithFullResponse: true
;

rp(options)
    .then (function (response) 
        var $ = cheerio.load(response.body);

        return $('img').map(function () 
            return url.resolve(base, $(this).attr('src'));
        ).toArray();
    )
    .then(console.log);

url.resolve 将适用于绝对或相对 URL(当从您的请求 URL 解析为相对路径时,它会解析并返回组合的绝对 URL,但当从您的请求 URL 解析为绝对 URL 时,它只会返回绝对 URL网址)。例如,在谷歌上使用/logos/cat.gifhttps://test.com/dog.gif 作为src 属性的img 标签,这将输出:

[ 
    'http://www.google.com/logos/cat.gif',
    'https://test.com/dog.gif'
]

【讨论】:

【参考方案3】:

看起来你正在使用 jQuery,所以你可以

$('img').each(function(i, e) 
    console.log(e.src)
);

如果您使用src,它会将相对路径扩展为绝对路径。

【讨论】:

正确,但 src 不是 jQuery 属性。这是标准的 javascript 这是一个 DOM 属性 - 你不必为 everything 使用 jQuery 有点迂腐,他使用的是 Cheerio,这是一个 NodeJS 模块,它使用类似 jQuery 的语法来遍历 DOM。此外,在这种情况下,访问 src 属性也无济于事,因为当他需要绝对路径时,它仍会返回根相对 URL(或 DOM 中的任何内容)。

以上是关于如何从 response.body 获取节点中 '<img src=''>' 的绝对路径的主要内容,如果未能解决你的问题,请参考以下文章

spring cloud gateway获取response body

Spring Cloud Gateway 获取Request和Response Body

请求包:response.body不是JSON

Gin获取Response Body引发的OOM

Retrofit 2.0如何获得反序列化错误response.body

Retrofit 2.0如何获得反序列化错误response.body