ホームページ  >  記事  >  バックエンド開発  >  php_PHP チュートリアルを使用して Web ページの本文コンテンツを抽出する例

php_PHP チュートリアルを使用して Web ページの本文コンテンツを抽出する例

WBOY
WBOYオリジナル
2016-07-13 10:12:461184ブラウズ

Webページのテキストコンテンツを抽出するphpの例

難しいのは、Webページの記事部分をどのように特定して保持し、その他の無駄な情報を削除するかであり、普遍的である必要があり、コレクションを定式化できないためです検索エンジンの結果にはさまざまなWebページがあるため、機関車規則などの目的の駅に基づいて検索できます。

ページのデータを取得してテキスト部分を照合するにはどうすればよいですか? Zheng Xiao は仕事を終える途中に次のアイデアを思いつきました。

1. bodyタグ部分を抽出 –>すべてのリンクを削除 –>すべての空白タグを削除 –>結果を取得します。

2. div、p、h タグに一致する、リンクされていない中国語部分を直接一致させます???

ボトム情報など、他にも多くの冗長な情報がまだあります。 。 どうすればいいですか?何かアイデアや提案はありますか?

このクラスは、インターネット上で見つかったPHPで実装されたWebページのテキスト部分を抽出するアルゴリズムで、Zheng Xiaoもローカルでテストしており、精度が非常に高いです。

コードは次のとおりです

クラスの可読性 {

// 判定結果のマークビット名を保存
const ATTR_CONTENT_SCORE = "コンテンツスコア";

// DOM 解析クラスは現在 UTF-8 エンコーディングのみをサポートしています

const DOM_DEFAULT_CHARSET = "utf-8";

//判定失敗時の表示内容

const MESSAGE_CAN_NOT_GET = "このページのコンテンツを読みやすく解析できませんでした。";

// DOM 解析クラス (PHP5 に組み込まれています)

保護された $DOM = null;

//解析が必要なソースコード

protected $source = "";

//章の親要素のリスト

private $parentNodes = array();

// 削除する必要があるタグ
// 注: http://www.45it.net から追加のタグを追加しました

private $junkTags = Array("style", "form", "iframe", "script", "button", "input", "textarea",
「noscript」、「select」、「option」、「object」、「applet」、「basefont」、
"bgsound"、"blink"、"canvas"、"command"、"menu"、"nav"、"datalist"、
"埋め込み"、"フレーム"、"フレームセット"、"keygen"、"ラベル"、"マーキー"、"リンク");

//削除する必要がある属性
private $junkAttrs = Array("style", "class", "onclick", "onmouseover", "align", "border", "margin");


/**
*コンストラクター
* @param $input_char 文字列のエンコーディング。デフォルトはutf-8ですが、省略可能です
*/
function __construct($source, $input_char = "utf-8") {
$this->source = $source;

// DOM 解析クラスは UTF-8 形式の文字のみを処理できます
$source = mb_convert_encoding($source, 'HTML-ENTITIES', $input_char);

// HTML タグを前処理し、冗長なタグを削除します。
$source = $this->preparSource($source);

//DOM 解析クラスを生成する
$this->DOM = new DOMDocument('1.0', $input_char);
試してみてください{
//libxml_use_internal_errors(true);
// いくつかのエラー メッセージが表示されますが、問題ありません :^)
if (!@$this->DOM->loadHTML(''.$source)) {
throw new Exception("HTML 解析エラー!");
}

foreach ($this->DOM->childNodes as $item) {
if ($item->nodeType == XML_PI_NODE) {
$this->DOM->removeChild($item) // ハックを削除します
; }
}

//適切に挿入
$this->DOM->encoding = 可読性::DOM_DEFAULT_CHARSET;
} catch (例外 $e) {
// ...
}
}


/**
* DOM 解析クラスで正確に処理できるように HTML タグを前処理します
*
* @return 文字列
*/
プライベート関数 preparSource($string) {
// 解析エラーを避けるために、冗長な HTML エンコード タグを削除します
preg_match("/charset=([\w|\-]+);?/", $string, $match);
if (isset($match[1])) {
$string = preg_replace("/charset=([\w|\-]+);?/", "", $string, 1);
}

// 二重化されたすべての
を置き換えます。

の付いたタグタグを削除し、フォントを削除します。
$string = preg_replace("/[ \r\n\s]*/i", "

", $string );
$string = preg_replace("/gt;]*>/i", "", $string);

// @https://github.com/feelinglucky/php-readability/issues/7を参照
// - http://stackoverflow.com/questions/7130867/remove-script-tag-from-html-content から
$string = preg_replace("#(.*?)#is", "", $string);

トリムを返す($string);
}


/**
* DOM 要素からすべての $TagName タグを削除します
*
* @return DOMDocument
*/
プライベート関数removeJunkTag($RootNode, $TagName) {

$Tags = $RootNode->getElementsByTagName($TagName);

//注: タグを削除すると結果からもタグが削除されるため、常にインデックス 0 を指定してください。
while($Tag = $Tags->item(0)){
$parentNode = $Tag->parentNode;
$parentNode->removeChild($Tag);
}

$RootNode を返します;

}

/**
* 要素から不要な属性をすべて削除します
*/
プライベート関数removeJunkAttr($RootNode, $Attr) {
$Tags = $RootNode->getElementsByTagName("*");

$i = 0;
while($Tag = $Tags->item($i++)) {
$Tag->removeAttribute($Attr);
}

$RootNode を返す;
}

/**
* 評価に基づいてページのメインコンテンツのボックスモデルを取得します
* 決定アルゴリズムは http://code.google.com/p/arc90labs-readability/
から取得しました。 ※鄭暁さんのブログから転載させていただきました
* @return DOMNode
*/
プライベート関数 getTopBox() {
// 获得页面全部的章节
$allParagraphs = $this->DOM->getElementsByTagName("p");

// すべての段落を調べて、最高のスコアを持つチャンクを見つけます。
// スコアは次のようなものによって決定されます:

の数、カンマ、特殊クラスなど
$i = 0;
while($paragraph = $allParagraphs->item($i++)) {
$parentNode = $paragraph->parentNode;
$contentScore = intval($parentNode->getAttribute(Readability::ATTR_CONTENT_SCORE));
$className = $parentNode->getAttribute("クラス");
$id = $parentNode->getAttribute("id");

// 特別なクラス名を探します
if (preg_match("/(コメント|メタ|フッター|脚注)/i", $className)) {
$contentScore -= 50;
else if(preg_match(
"/((^|\\s)(post|hentry|entry[-]?(content|text|body)?|article[-]?(content|text|body)?)(\\s|$) )/私"、
$className)) {
$contentScore += 25;
}

// 特別なIDを探してください
if (preg_match("/(コメント|メタ|フッター|脚注)/i", $id)) {
$contentScore -= 50;
else if (preg_match(
"/^(post|hentry|entry[-]?(content|text|body)?|article[-]?(content|text|body)?)$/i",
$id)) {
$contentScore += 25;
}

// 見つかった段落にポイントを追加します
// この段落内のカンマにポイントを追加します
if (strlen($paragraph->nodeValue) > 10) {
$contentScore += strlen($paragraph->nodeValue);
}

//保存父元素の判定得分
$parentNode->setAttribute(Readability::ATTR_CONTENT_SCORE, $contentScore);

// 保存章节的父元素,便次快速获取
array_push($this->parentNodes, $parentNode);
}

$topBox = null;

// パフォーマンスのためのインデックスからの代入
// http://www.peachpit.com/articles/article.aspx?p=31567&seqNum=5 を参照してください
for ($i = 0, $len = sizeof($this->parentNodes); $i $parentNode = $this->parentNodes[$i];
$contentScore = intval($parentNode->getAttribute(Readability::ATTR_CONTENT_SCORE));
$orgContentScore = intval($topBox ? $topBox->getAttribute(Readability::ATTR_CONTENT_SCORE) : 0);

if ($contentScore && $contentScore > $orgContentScore) {
$topBox = $parentNode;
}
}

// この時点で$topBoxが決定されたページコンテンツのメイン要素となるはずです
$topBox を返します;
}


/**
* HTML ページのタイトルを取得します
*
* @return 文字列
*/
パブリック関数 getTitle() {
$split_point = ' - ';
$titleNodes = $this->DOM->getElementsByTagName("title");

if ($titleNodes->length
&& $titleNode = $titleNodes->item(0)) {
// @ http://stackoverflow.com/questions/717328/how-to-explode-string-right-to-left を参照
$title = トリム($titleNode->nodeValue);
$result = array_map('strrev',explode($split_point, strrev($title)));
サイズを返します($result) > 1? array_pop($result) : $title;
}

null を返す;
}


/**
* 先頭の画像 URL を取得します
*
* @return 文字列
*/
パブリック関数 getLeadImageUrl($node) {
$images = $node->getElementsByTagName("img");

if ($images->length && $leadImage = $images->item(0)) {
return $leadImage->getAttribute("src");
}

null を返す;
}


/**
* ページのメインコンテンツ (Readability 後のコンテンツ) を取得します
*
* @return 配列
*/
パブリック関数 getContent() {
if (!$this->DOM) が false を返す;

//ページタイトルを取得します
$ContentTitle = $this->getTitle();

// ページのメインコンテンツを取得します
$ContentBox = $this->getTopBox();

// 適切なトップボックスが見つかったかどうかを確認します。
if($ContentBox === null)
throw new RuntimeException(Readability::MESSAGE_CAN_NOT_GET);

// コンテンツを新しい DOMDocument にコピーします
$Target = 新しい DOMDocument;
$Target->appendChild($Target->importNode($ContentBox, true));

//不要なタグを削除
foreach ($this->junkTags を $tag として) {
$Target = $this->removeJunkTag($Target, $tag);
}

//不要な属性を削除
foreach ($this->junkAttrs as $attr) {
$Target = $this->removeJunkAttr($Target, $attr);
}

$content = mb_convert_encoding($Target->saveHTML(), Readability::DOM_DEFAULT_CHARSET, "HTML-ENTITIES");

//配列の形式で返される複数のデータ
配列を返す(
'lead_image_url' => $this->getLeadImageUrl($Target),
'word_count' => mb_strlen(strip_tags($content), 可読性::DOM_DEFAULT_CHARSET),
'タイトル' => $ContentTitle : null,
'コンテンツ' => $コンテンツ
);
}

関数 __destruct() { }
}

使い方も非常に簡単で、インスタンス化するときに、Web ページの HTML ソース コードと対応するエンコーディングを渡し、その getContent メソッドを直接呼び出して、抽出されたテキスト部分を返します。リンクをしてください。後で変更します

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/919973.html技術記事ウェブページの記事部分をどのように特定して保持し、その他の無駄な情報を削除するかが難しいため、ウェブページのテキストコンテンツを抽出するphpの例。それは普遍的でなければならず、電車のようなものであってはなりません...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。