ducwp/readability.php

Readability.js 的 PHP 版本

安装: 0

依赖项: 0

建议者: 0

安全性: 0

星标: 0

关注者: 0

分支: 89

语言:HTML

dev-master 2022-08-26 15:38 UTC

This package is auto-updated.

Last update: 2024-09-26 20:32:45 UTC


README

新闻(2021年8月)

Readability.php 的原始开发者 Andres Rey 好意地将项目的维护和开发权交给了我们。

在我们将 Readability.js 的变更更新完毕之前,请耐心等待。当我们准备就绪时,将会有一个新版本(3.0.0)发布。

关于这个存储库中我们已做的变更,请参阅我们的 博客文章

关于

Latest Stable Version Tests

PHP 版本的 MozillaReadability.js。它解析 html 文本(通常是新闻和其他文章),并返回无导航栏、广告、页脚或任何不是正文主体的内容,包括 标题作者主图片文本内容。它分析每个节点,为它们评分,并确定哪些是相关的,哪些可以丢弃。

Screenshot

该项目旨在成为 Mozilla 版本的 1:1 端口,并紧密跟踪那里引入的所有变更,但在结构上存在一些主要差异。大部分代码是 1:1 复制的——甚至注释也被导入——但某些功能和结构被调整以更好地适应 PHP 语言。

原始开发者: Andres Rey

开发者/维护者: FiveFilters.org

代码移植

主分支 - 截至 2021 年 8 月 26 日更新,除了一块 代码 之外,它与 JS 版本在 PHP 中产生的结果不同。可能存在错误,或者底层代码中的一些差异影响了这一点。如果您知道哪里出了问题,请随时联系我们或提交一个 pull request。 :)

版本 2.1.0 - 与 Readability.js 保持一致,更新到 2018 年 11 月 19 日

要求

PHP 7.3+,ext-dom,ext-xml 和 ext-mbstring。如果您系统上还没有这些依赖项,可以在类似 *nix 的环境中尝试以下操作

$ sudo apt-get install php7.4-xml php7.4-mbstring

如何使用它

首先,您需要使用 composer 包含这个库

composer require fivefilters/readability.php

然后,创建一个 Readability 类并传递一个 Configuration 类,用您的 HTML 填充 parse() 函数,并输出变量

use fivefilters\Readability\Readability;
use fivefilters\Readability\Configuration;
use fivefilters\Readability\ParseException;

$readability = new Readability(new Configuration());

$html = file_get_contents('http://your.favorite.newspaper/article.html');

try {
    $readability->parse($html);
    echo $readability;
} catch (ParseException $e) {
    echo sprintf('Error processing text: %s', $e->getMessage());
}

您的脚本将输出解析后的文本或通知任何错误。您应该始终将 ->parse 调用包裹在 try/catch 块中,因为如果 HTML 无法正确解析,将抛出 ParseException

如果您想要更精细地控制输出,只需逐个调用属性,并用您自己的 HTML 包裹它们。

<h1><?= $readability->getTitle(); ?></h1>
<h2>By <?= $readability->getAuthor(); ?></h2>
<div class="content"><?= $readability->getContent(); ?></div>

以下是可用的属性列表

  • 文章标题:->getTitle();
  • 文章内容:->getContent();
  • 摘要:->getExcerpt();
  • 主图片:->getImage();
  • 所有图片:->getImages();
  • 作者:->getAuthor();
  • 文本方向(ltr 或 rtl):->getDirection();

如果您需要调整最终 HTML,可以通过调用 ->getDOMDocument() 获取结果的 DOMDocument。

选项

您可以通过配置对象来更改Readability的行为。例如,如果您想修复相对URL并声明原始URL,可以设置配置如下

$configuration = new Configuration();
$configuration
    ->setFixRelativeURLs(true)
    ->setOriginalURL('http://my.newspaper.url/article/something-interesting-to-read.html');

您还可以将配置参数数组传递给构造函数

$configuration = new Configuration([
    'fixRelativeURLs' => true,
    'originalURL'     => 'http://my.newspaper.url/article/something-interesting-to-read.html',
    // other parameters ... listing below
]);

然后,将此配置对象传递给Readability。以下是一些可用选项。记住,在调用原生设置器时,要使用前缀set

  • MaxTopCandidates:默认值5,顶级候选者的最大数量。
  • CharThreshold:默认值500,考虑文章解析成功的最小字符数。
  • ArticleByLine:默认值false,通过搜索文章作者行并将其从文本中删除。它将被移动到文章元数据中。
  • StripUnlikelyCandidates:默认值true,删除不太可能包含相关信息的节点。对于调试或解析复杂或非标准文章很有用。
  • CleanConditionally:默认值true,在解析后删除某些节点以返回更干净的结果。
  • WeightClasses:默认值true,在评分阶段进行加权。
  • FixRelativeURLs:默认值false,将相对URL转换为绝对URL。例如,将/test转换为http://host/test
  • SubstituteEntities:默认值false,禁用libxml的substituteEntities标志。将避免替换HTML实体。例如,将&aacute;转换为á。
  • NormalizeEntities:默认值false,将UTF-8字符转换为其HTML实体等效。用于解析具有混合编码的HTML。
  • OriginalURL:默认值http://fakehost,用于修复相对URL的文章原始URL。
  • KeepClasses:默认值false,它将从HTML元素中删除所有class="..."属性值。
  • Parser:默认值html5,它使用HTML5-PHP进行解析。设置为libxml以使用该工具(不推荐用于现代HTML文档)。
  • SummonCthulhu:默认值false,通过正则表达式删除所有<script>节点。这不是理想的选择,因为它可能会破坏某些东西,但如果您已将解析器设置为libxml(如上所述),则可能是唯一的解决方案,以解决libxml与未转义JavaScript的问题

调试日志

记录是可选的,您需要注入自己的记录器来保存所有调试消息。为此,使用实现PSR-3记录接口的记录器,并将其传递给配置对象。例如

// Using monolog

$log = new Logger('Readability');
$log->pushHandler(new StreamHandler('path/to/my/log.txt'));

$configuration->setLogger($log);

在日志中,您将找到有关解析节点、为什么删除它们以及为什么它们被认为是最终文章的相关信息。

限制

当然,主要限制是PHP。通过懒加载、AJAX或任何类型的JavaScript驱动的调用加载内容的网站将被忽略(实际上,未运行),与readability.js的结果相比,生成的文本将是错误的。您希望使用readability.php解析的所有文章都必须完整,并且所有内容都应该已经在HTML中。

已知的libxml解析问题

Readability.php从3.0.0版本开始使用HTML5解析器。早期版本使用libxml。以下问题适用于libxml解析,因此如果您正在使用Readability.php的早期版本(3.0.0之前),或者如果已在配置中设置了解析器为libxml,请继续阅读...

JavaScript溢出到文本体中

DOMDocument在解析具有未转义HTML的字符串时存在一些问题。考虑以下代码

<div> <!-- Offending div without closing tag -->
<script type="text/javascript">
       var test = '</div>';
       // I should not appear on the result
</script>

如果您想要删除HTML中的脚本(如readability所做的),您可能会希望最终得到一个div标签和一个注释。问题在于libxml将那个关闭的div标签视为javascript字符串中的HTML标签,从而有效地关闭了未关闭的标签,并将剩余的javascript作为一个字符串留在p标签内。如果您保存这个节点,最终的HTML将如下所示:

<div> <!-- Offending div without closing tag -->
<p>';
       // I should not appear on the result
</p></div>

这是一个libxml问题,而不是Readability.php的bug。

有一个解决方法:使用summonCthulhu选项。这将通过正则表达式删除所有的脚本标签,这不是理想的做法,因为您可能会招来黑暗的领主

&nbsp实体消失

&nbsp实体会被libxml自动转换为空格,并且无法禁用此功能。

自闭合标签渲染为完全展开的标签

自闭合标签,如<br />会被自动展开为<br></br。在libxml中无法禁用此功能。

依赖项

Readability.php使用

  • HTML5-PHP来解析和序列化HTML。
  • PSR Log接口来定义允许的日志记录器类型。
  • Monolog仅在开发安装中需要。(在composer install时使用--dev选项)。

待办事项

  • 跟踪Readability.js的更改
  • 为__toString()方法添加一个小的模板引擎,而不是使用硬编码的一个。
  • 将所有的iterator_to_array调用替换为一个自定义的PHP生成器,该生成器可以跟踪已删除或更改的节点。

它是如何工作的

Readability使用DOMDocument解析所有文本,扫描文本节点并根据单词数量、链接和元素类型给予分数。然后它选择得分最高的元素,并创建一个包含所有同级元素的新DOMDocument。每个同级元素都会被评分,以删除无用的元素,如导航栏、空节点等。

安全性

如果您打算使用Readability处理不受信任的输入(无论是HTML还是DOM形式),我们强烈建议您使用像HTML Purifier这样的清理库,以避免在读取Readability的输出时发生脚本注入。我们还建议使用CSP来为允许的最终内容添加额外的防御深度限制。Firefox的阅读模式集成本身也使用了这两种技术。明确地说,从输入中清理不安全的内容不是Readability本身的目标 - 有其他很好的清理库,请使用它们!

测试

安装本地PHP 7.3及以上版本应该足以开发新功能并添加新测试用例。如果您想确保您的更改不会与其他版本的PHP版本产生问题,您可以使用提供的Docker容器来测试目前7.3、7.4和8.0的版本。

为此,您需要Docker和Docker Compose。要运行上述三个PHP版本的测试,请输入以下命令

make test-all

这将启动所有容器,并在每个受支持的PHP版本上运行所有测试。如果您想针对特定版本进行测试,可以使用make test-7.3make test-7.4make test-8

不同版本的libxml

如果您想针对支持的PHP版本以及多个版本的libxml进行测试,请运行test-all-versions。这将测试PHP版本7.3到8,以及libxml版本2.9.4、2.9.5、2.9.10和2.9.12。通常情况下,除非您认为您在特定的libxml版本上找到了一个bug,否则您不需要这样做。

更新预期的测试

如果您对代码进行了改进,您可能想检查这里的测试用例的 Readability.php 输出。为此,首先从项目文件夹的根目录运行以下命令:

docker-compose up -d php-7.4-libxml-2.9.10

现在,您应该有一个运行的 Docker 镜像,项目根文件夹映射到 Docker 实例上的 /app/(见 docker-compose.yml)。从现在开始,对这些文件的任何更改都将可通过 Docker 实例访问。

接下来,在 tests/ 目录下创建一个名为 /changed 的文件夹,然后运行以下命令来运行测试套件:

docker-compose exec -e output-changes=1 -e output-diff=1 php-7.4-libxml-2.9.10 php /app/vendor/phpunit/phpunit/phpunit --configuration /app/phpunit.xml

两个环境变量(output-changes=1output-diff=1)会导致任何失败的测试输出新的输出(包括更改的 diff),并将其写入 changed/ 文件夹。

如果您认为更改是好的,设置 output-diff=0,diff 文件将不再写入,这使得将新的预期输出文件复制到 test-pages 中对应的位置更容易。

许可

基于 Arc90 的 readability.js(1.7.1)脚本,可在以下地址获取:http://code.google.com/p/arc90labs-readability

Copyright (c) 2010 Arc90 Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   https://apache.ac.cn/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.