【发布时间】:2018-04-15 14:14:01
【问题描述】:
我有一些代码使用新的 ES6 fetch API 并嵌套了 fetch 调用。第一次 fetch 获取一个文档,其中包含一些锚点。对于每个锚点,我都会进行另一次抓取。这是代码。
我进行了一次提取,获取响应文本,将其解析为 HTML 并将 DOM 传递给另一个函数。
我从文档中选择一些锚点,并检查每个锚点是否合适,然后进行第一次记录。这会记录六个不同的 URL。
现在我为这六个 URL 中的每一个进行嵌套提取。该代码与第一次提取几乎相同。我只是记录响应 URL 以确保我有不同的响应。第二个日志记录还显示了 6 个不同的 URL。我再次解析响应文本并将 DOM 传递给另一个函数。
现在变得有趣了。我对 DOM 做的第一件事是打印文档 URL。这会打印六次相同的 URL。为什么在四行之前已经记录了六个不同的 URL,但它打印了六次相同的 URL?
一定有某种副作用,但我不明白它在哪里。我有不同的响应,我为每个响应创建一个新的 DOM 解析器。怎么会有副作用?
// 1.
fetch('https://eu.battle.net/d3/de/item/two-handed/')
.then(response => response.text())
.then(text => (new DOMParser()).parseFromString (text, 'text/html'))
.then(doc => {
// 2.
let urls = [];
doc.querySelectorAll('li.open a')
.forEach(node => {
if (!node.href.match(/flail|mighty-weapon|scythe/g)) {
console.log ("1: " + node.href); // Prints 6 different URLs.
// 3.
fetch(node.href)
.then(response => {
console.log ("2: " + response.url); // Prints 6 different URLs.
return response.text()
})
.then(text => (new DOMParser()).parseFromString (text, 'text/html'))
.then(doc => {
// 4.
console.log ("3: " + doc.URL); // Prints first URL six times.
doc.querySelectorAll('.top .ui-pagination a')
.forEach(node => {
urls.push(node.href);
});
});
}
});
return urls;
});
【问题讨论】:
-
也许
response.text()为每个请求返回相同的内容? -
鉴于文档是通过
(new DOMParser()).parseFromString (text, 'text/html')创建的,doc.URL的值是多少? -
所以
doc.URL打印运行此 javascript 的任何位置的 url,不一定是构造文档的源的 url。所以我认为它正在打印您正在运行的页面的网址,而不是每个文档的来源。这是有道理的,因为您只将 html 提供给 DOMParser,它怎么知道 html 是从哪个来源收集的? -
当我做
(new DOMParser()).parseFromString('<div></div>', 'text/html').URL时,无论我传入什么值,我总是得到相同的值。所以看起来结果是预期的?node.href和doc.URL根本没有关系。 -
@CRice 这似乎是问题所在。
parseFromString不知道 URL。而后面的node.href因此返回了错误的 URL,因为在这个特定的文档中它是一个相对 URL。这导致了如何告诉 DOMParser 正确的 URL 的问题。