1

我正在做一个个人项目来离线查看网页。我想出的第一个想法是使用file_get_contents获取特定 url 的内容,但这只会获取 html 而不是该页面中的资产(css、图像、javascript 等)。所以我不得不编写正则表达式来获取页面中的样式表和图像:

$css_pattern = '/\S*\.css"/';
$img_src_pattern = '/src=(?:"|\')?.+\.(?:gif|jpg|png|jpeg)(?:"|\')/';
preg_match_all($css_pattern, $contents, $style_matches);
preg_match_all($img_src_pattern, $contents, $img_matches);

这可行,但css中也有图像链接。我还在思考如何处理这些问题。

还有一些项目,如ganon https://code.google.com/p/ganon/和简单的 html 解析器,它们可能会让我的生活更轻松,但我更喜欢使用正则表达式,因为我想了解更多相关信息。

问题是:有没有更好的方法来做这个项目?该应用程序可能会有用于保存每个站点的资产和 html 的文件夹,它可能会变得笨拙。我听说过 html5 中的清单文件之类的东西,但如果您不拥有该网站,我不确定这是否可能。有任何想法吗?如果没有其他方法可以做到这一点,那么也许你可以帮助我改进我上面的正则表达式。我基本上必须使用str_replaceforeach获取样式表:

$stylesheets = array();
foreach($style_matches[0] as $match){
    $stylesheets[] = str_replace(array('href=', '"', "'"), '', $match);
}

提前致谢!

4

1 回答 1

2

我更喜欢使用正则表达式,因为我想了解更多有关它的信息。

使用正则表达式解析 HTML 是可能的,尽管并非易事。在下面的论文中给出了一个很好的介绍:

该论文中使用的正则表达式(REX)不是PHP(PCRE)中使用的,但是如果您愿意学习,应该能够理解它,它是相似的。

按照那篇论文的概述并用一些不错的测试用例自己用 PHP 编写正则表达式应该是你深入研究正则表达式的真正训练营。

在正则表达式旁边,您还需要处理字符编码,这是它自己的另一个字段,然后采用解析器进行编码(如果您在解析之前不重新编码)。

如果您正在专门寻找兼容 HTML 5 的解析器,它被指定为 HTML 5“规范”的一部分,但是您不能再以理智的方式使用正则表达式精确地做到这一点(至少据我所知)关于它):

对我来说,这种类型的解析看起来开销很大,但是看看 HTML 5 Parser 的概要,你就会知道现在你可以为 HTML 解析处理什么。看起来那些男孩和女孩真的需要把他们能想象到的任何东西都塞进去。实际上,以下引擎/浏览器具有 HTML 5 解析器:

从 PHP 生态系统的个人经验来看,没有那么多基于 SGML/“松散”/低级/标签汤的 HTML 解析器。如果我写一个,我也会使用正则表达式进行字符串解析,REX 浅解析文章有一些很好的讨论。但是,我可能只会使用这种低级 HTML 解析器来使任何 HTML 可用于 DOMDocument 或其他一些验证/修复相关的东西,并且不会将其用于进一步的解析/文档抽象。DOMDocument 非常强大,尤其是在收集您上面描述的链接方面。

对于剩下的问题,您会发现各种 HTTP 相关 RFC 中概述的所有需要​​组合在一起的元素,因此您需要自行决定要支持哪种链接解析算法以及如何重新映射静态 CSS/ image/js 文件,如果您再次保存它们。然后,您通常还会重新编写 DOMDocument 非常方便的 HTML。

此外,您应该通过 meta 元素在 HTML 文件中存储一些 HTTP 标头。特别是对于编码,除非您不重新编码(无论如何这对于离线阅读都很有用)。HTML 创作的一些更一般的问答建议也适用于静态缓存。

html5 清单文件实际上是不同的。原始服务器应该支持它。情况可能并非如此(或者您还需要构建它的解析器并对其进行处理)。因此,如果您创建一个镜像,您可能还需要指出可以在本地存储以供离线使用的所有静态资源。这是一个好主意,我还没有看到像 wget 这样的工具实现了这一点,所以可能值得尝试一下这个想法。

除了HTML5 清单文件,您可能还与以下容器格式之一相关:

这些格式/扩展中的另一种(此处:SingleFile Chrome 扩展)根据维基百科使用 Data URI 方案,这在这种情况下也可能有用,尽管我不喜欢它,我会说最好有一个算法它能够以可复制的方式将 URL 重写到本地文件系统,这样您就可以转储具有相同资产的多个 HTML 文件,而无需多次获取资产。

于 2013-03-31T12:40:53.400 回答