如何使用Simple HTML DOM将相对URL转换为绝对URL?

4

当我从某些页面抓取内容时,脚本会给出一个相对URL。是否可能使用Simple HTML DOM获取绝对URL?

3个回答

11
我认为Simple HTML DOM Parser无法做到这一点。
但是你可以自己做。首先,您需要区分基本URI,即文档的URI(如果未另行声明)(请参见BASE元素)。然后获取每个URI引用并应用在RFC 3986中描述的解析相对URI的算法(已经有可用于此的类,例如PEAR包Net_URL2)。
因此,使用这两个类,您可以执行以下操作:
$uri = new Net_URL2('http://example.com/foo/bar'); // URI of the resource
$baseURI = $uri;
foreach ($html->find('base[href]') as $elem) {
    $baseURI = $uri->resolve($elem->href);
}

foreach ($html->find('*[src]') as $elem) {
    $elem->src = $baseURI->resolve($elem->src)->__toString();
}
foreach ($html->find('*[href]') as $elem) {
    if (strtoupper($elem->tag) === 'BASE') continue;
    $elem->href = $baseURI->resolve($elem->href)->__toString();
}
foreach ($html->find('form[action]') as $elem) {
    $elem->action = $baseURI->resolve($elem->action)->__toString();
}

对于包含类似backgroundciteclassidcodebasedatalongdescprofileusemap等URI的任何其他属性,都需要重复进行替换(请参见HTML 4.01中属性的索引)。


0
除了@Artefacto的答案之外,如果您要在某个地方输出抓取的HTML,您可以简单地在文档头部添加<base href="http://example.com">,这将把指定的href作为文档中所有相对URL的基本URL。请参阅http://www.w3schools.com/tags/tag_base.asp

1
是的,我知道那个选项,但当我必须抓取两个或更多的网站时,这是不可能的。你可以在脚本中使用它来进行一次抓取,但当你想要抓取2个网站时,那就不可能了。 - Jean
@Jean,如果是这样的话,你需要通过编程来更改你所抓取的内容。 - karim79

-3

编辑 请参考Gumbo的答案以获得正式正确的答案。这是一个简化的算法,适用于绝大多数情况,但在某些情况下可能会失败。

当然可以。做这个:

  • 获取相对URL(不以http://https://或任何其他协议开头,也不以/开头的URL)。
  • 获取页面的URL。
  • 从中删除查询字符串(如果有)。一种简单的方法是explode围绕?并取结果数组的第一个元素(取索引0的元素或使用reset)。
    • 如果页面的URL以/结尾,则将其附加到相对URL上,即可得到最终URL。
    • 如果URL不以/结尾,则获取其dirname,并将其附加到相对URL上。现在您已经获得了最终URL。

谢谢您的回答,但我该如何在脚本中编写这个程序呢? - Jean
谢谢大家,我会尝试的。 - Jean
@Jean 这里概述了脚本的算法;如果你还有困难,可以发跟进问题。 - Artefacto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接