本文目录导读:

我来提供几种PHP网页正文提取的方案,从简单到复杂:
方案1:使用第三方库(推荐)
使用 html2text 库
composer require html2text/html2text
<?php
require 'vendor/autoload.php';
use Html2Text\Html2Text;
$html = file_get_contents('https://example.com/article');
$converter = new Html2Text($html);
echo $converter->getText();
使用 goutte (基于Symfony DomCrawler)
composer require fabpot/goutte
<?php
require 'vendor/autoload.php';
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'https://example.com/article');
内容
$content = $crawler->filter('article')->first()->text();
echo $content;
方案2:使用正则表达式提取
<?php
class ContentExtractor {
private $html;
public function __construct($html) {
$this->html = $html;
}
/**
* 简单正文提取
*/
public function extractSimple() {
// 去除script和style标签
$html = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $this->html);
$html = preg_replace('/<style\b[^>]*>(.*?)<\/style>/is', '', $html);
// 去除注释
$html = preg_replace('/<!--(.*?)-->/is', '', $html);
// 去除HTML标签
$text = strip_tags($html);
// 处理空白字符
$text = preg_replace('/\s+/', ' ', $text);
$text = trim($text);
return $text;
}
/**
* 高级正文提取(基于常见正文标签)
*/
public function extractAdvanced() {
$patterns = [
'/<article[^>]*>(.*?)<\/article>/is',
'/<div[^>]*class=["\']article["\'][^>]*>(.*?)<\/div>/is',
'/<div[^>]*id=["\']content["\'][^>]*>(.*?)<\/div>/is',
'/<div[^>]*class=["\']content["\'][^>]*>(.*?)<\/div>/is',
'/<div[^>]*class=["\']post["\'][^>]*>(.*?)<\/div>/is',
];
foreach ($patterns as $pattern) {
if (preg_match($pattern, $this->html, $matches)) {
$content = $this->cleanHtml($matches[1]);
return $content;
}
}
return $this->extractSimple();
}
private function cleanHtml($html) {
$html = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $html);
$html = preg_replace('/<style\b[^>]*>(.*?)<\/style>/is', '', $html);
$html = preg_replace('/<!--(.*?)-->/is', '', $html);
$text = strip_tags($html);
$text = preg_replace('/\s+/', ' ', $text);
return trim($text);
}
}
// 使用示例
$html = file_get_contents('your_html_file.html');
$extractor = new ContentExtractor($html);
$content = $extractor->extractAdvanced();
echo $content;
方案3:使用DOMDocument和XPath
<?php
class DOMContentExtractor {
private $dom;
private $xpath;
public function __construct($html) {
$this->dom = new DOMDocument();
// 使用libxml来避免HTML5标签警告
libxml_use_internal_errors(true);
$this->dom->loadHTML('<?xml encoding="UTF-8">' . $html, LIBXML_NOERROR);
libxml_clear_errors();
$this->xpath = new DOMXPath($this->dom);
}
/**
* 根据常用选择器提取正文
*/
public function extractBySelectors() {
$selectors = [
'//article',
'//*[contains(@class, "article")]',
'//*[contains(@class, "content")]',
'//*[contains(@class, "post")]',
'//div[@id="content"]',
];
foreach ($selectors as $selector) {
$nodes = $this->xpath->query($selector);
if ($nodes->length > 0) {
return $this->getTextContent($nodes->item(0));
}
}
return null;
}
/**
* 智能提取:根据文本密度
*/
public function extractSmart() {
$blocks = $this->xpath->query('//div | //p | //article | //section');
$bestBlock = null;
$maxScore = 0;
foreach ($blocks as $block) {
$text = $block->textContent;
$score = $this->calculateTextDensity($text);
if ($score > $maxScore) {
$maxScore = $score;
$bestBlock = $block;
}
}
if ($bestBlock) {
return $this->getTextContent($bestBlock);
}
return null;
}
private function calculateTextDensity($text) {
// 文本密度计算
$text = trim(preg_replace('/\s+/', ' ', $text));
$chars = mb_strlen($text);
$links = substr_count($text, '<a');
// 简单的文本密度评分
return $chars - ($links * 10);
}
private function getTextContent(DOMNode $node) {
$text = $node->textContent;
return trim(preg_replace('/\s+/', ' ', $text));
}
}
// 使用示例
$html = file_get_contents('your_html_file.html');
$extractor = new DOMContentExtractor($html);
$content = $extractor->extractSmart();
echo $content;
方案4:综合使用的完整示例
<?php
require 'vendor/autoload.php';
use DiDom\Document;
class ArticleExtractor {
private $url;
private $content;
public function __construct($url) {
$this->url = $url;
}
public function fetch() {
// 获取HTML
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
$html = curl_exec($ch);
curl_close($ch);
// 使用DiDom解析
$document = new Document($html);
return $this->extractContent($document);
}
private function extractContent(Document $document) {
$selectors = [
'article',
'.article',
'.content',
'.post',
'#content',
'.main-content'
];
foreach ($selectors as $selector) {
$elements = $document->find($selector);
if (count($elements) > 0) {
$this->content = $elements[0]->text();
return $this->content;
}
}
return null;
}
public function getTitle(Document $document) {
$titleElement = $document->find('title');
if (count($titleElement) > 0) {
return $titleElement[0]->text();
}
return null;
}
}
// 使用
try {
$extractor = new ArticleExtractor('https://example.com/article');
$contents = $extractor->fetch();
echo $contents;
} catch (Exception $e) {
echo 'Error: ' . $e->getMessage();
}
注意事项
- 编码问题:确保处理UTF-8编码
- 链接检测:可以过滤掉包含大量链接的区块
- 图片处理:可以选择保留或移除图片
- 性能优化:对大HTML文件使用流式处理
- 反爬虫:注意网站的使用条款
推荐库列表
- Html2Text:简单转换
- DOMDocument + XPath:PHP内置,灵活
- Goutte:Web爬虫和测试
- DiDom:简单易用的DOM操作
- Readability.php:类似Mozilla的Readability算法
选择哪个方案取决于你的具体需求,最简单的场景可以用正则表达式方案,复杂的抽取建议使用DOMDocument或第三方库。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播