No description
  • PHP 97.6%
  • Shell 1.5%
  • JavaScript 0.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-03 11:50:51 -04:00
lib Clean up XPath wrapper slightly 2026-09-03 11:50:51 -04:00
scripts Various fixes and enhancements 2026-09-01 18:09:35 -04:00
tests Documentation tweaks 2026-09-01 22:02:38 -04:00
upstream@ab4027a8b3 Sync with upstream 2026-08-20 13:24:20 -04:00
vendor-bin/phpunit Get rid of Robo 2026-09-01 10:15:45 -04:00
.gitattributes Add boilerplate 2024-06-24 12:12:50 -04:00
.gitignore Various fixes and enhancements 2026-09-01 18:09:35 -04:00
.gitmodules Add boilerplate 2024-06-24 12:12:50 -04:00
.php-cs-fixer.dist.php Add boilerplate 2024-06-24 12:12:50 -04:00
composer.json Use own polyfills rather than Symfony's 2026-09-03 11:01:10 -04:00
composer.lock Use own polyfills rather than Symfony's 2026-09-03 11:01:10 -04:00
LICENSE Add boilerplate 2024-06-24 12:12:50 -04:00
package-lock.json Various fixes and enhancements 2026-09-01 18:09:35 -04:00
package.json Various fixes and enhancements 2026-09-01 18:09:35 -04:00
README.md Use own polyfills rather than Symfony's 2026-09-03 11:01:10 -04:00

Readability for PHP

This is a port of Readability to PHP. Much like the other port now maintained by Fivefilters, it is a line-by-line translation, so they do not differ that much. However there are a few differences:

  • We support PHP versions as far back as 8.0
  • Either Dom\HTMLDocument or DOMDocument instances are accepted as input
  • The mbstring extension is not required (though either it or the intl extension will be used if available)
  • The API more closely matches the original (though it is not quite the same)
  • Unicode characters above U+FFFF are counted twice as in JavaScript
  • None of Fivefilters' extra options are supported
  • Relative URLs are always resolved

Usage

Distilling a document

As with the JavaScript original, a parsed HTML document is required as input; this document will be modified in-place. Additionally, a document URL is required; the original assumed that document.documentURI is set, but this is usually not true in a PHP context. The same options accepted by Readability are accepted by this port, as an associative array.

use MensBeam\HTML\DOMParser;
use MensBeam\Readability\Readability;

$url = "https://arstechnica.com/";
$html = file_get_contents($url);
// The DOMParser class will accurately parse HTML and return a Dom\HTMLDocument when possible
$document = (new DOMParser)->parseFromString($htnl, "text/html;charset=utf-8");

$options = ['keepClasses' => ["foo", "bar"], 'debug' => true];
$readability = new Readability($document, $url, $options);
$output = $readability->parse();
// The output can be null
if ($output) {
    echo $output['content'];
}

Testing a document

Readability includes a much simpler algorithm to determine whether Readability would likely not yield good results, making loading its expensive algorithm not worthwhile. Readability makes this available in a separate file to also save the network transfer of the Readability code, but we include it in the same class as a static method. Our API is otherwise identical.

use MensBeam\HTML\DOMParser;
use MensBeam\Readability\Readability;

$html = file_get_contents($url);
// The DOMParser class will accurately parse HTML and return a Dom\HTMLDocument when possible
$document = (new DOMParser)->parseFromString($htnl, "text/html;charset=utf-8");

$options = ['minScore' => 25];
$output Readability::isProbablyReaderable($document, $options);
var_export($output);