亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

php preg_match 排除 html 標簽/屬性中的文本以找到剪切字符串的正確位置

php preg_match 排除 html 標簽/屬性中的文本以找到剪切字符串的正確位置

PHP
一只萌萌小番薯 2023-04-28 16:38:05
我試圖確定某些單詞在 html 塊中的絕對位置,但前提是它們在實際的 html 標記之外。例如,如果我想在本文中使用 preg_match 確定單詞“join”的位置:<p>There are 14 more days until our <a href="/somepage.html" target="_blank" rel="noreferrer noopener" aria-label="join us">holiday special</a> so come join us!</p>我可以使用:preg_match('/join/', $post_content, $matches, PREG_OFFSET_CAPTURE, $offset);問題是這是在匹配 aria-label 屬性中的詞,而我需要的是緊接在鏈接之后的詞。可以在<a>和之間進行匹配</a>,只是不在括號內。我的實際最終目標是(我認為)除了最后一個元素之外的大部分內容:我正在修剪一個 html 塊(不是完整的文檔)以在特定的字數處截斷。我試圖確定最后一個單詞以哪個字符結尾,然后將 html 塊的左側與右側的 html 連接起來,因此所有 html 標簽都可以優雅地關閉。我以為我讓它工作了,直到我遇到一個例子,比如我展示了最后一個詞也在 html 屬性中,導致我在錯誤的位置拆分字符串。到目前為止,這是我的代碼:$post_content = strip_tags ( $p->post_content, "<a><br><p><ul><li>" );$post_content_stripped = strip_tags ( $p->post_content );$post_content_stripped = preg_replace("/[^A-Za-z0-9 ]/", ' ', $post_content_stripped);$post_content_stripped = preg_replace("/\s+/", ' ', $post_content_stripped);$post_content_stripped_array = explode ( " " , trim($post_content_stripped) );$excerpt_wordcount = count( $post_content_stripped_array );$cutpos = 0;while($excerpt_wordcount>48){    $thiswordrev = "/" . strrev($post_content_stripped_array[$excerpt_wordcount - 1]) . "/";    preg_match($thiswordrev, strrev($post_content), $matches, PREG_OFFSET_CAPTURE, $cutpos);    $cutpos = $matches[0][1] + (strlen($thiswordrev) - 2);    array_pop($post_content_stripped_array);    $excerpt_wordcount = count( $post_content_stripped_array );}if($pwordcount>$excerpt_wordcount){    preg_match_all('/<\/?[^>]*>/', substr( $post_content, strlen($post_content) - $cutpos ), $closetags_result);    $excerpt_closetags = "" . $closetags_result[0][0];    $post_excerpt = substr( $post_content, 0, strlen($post_content) - $cutpos ) . $excerpt_closetags;}else{    $post_excerpt = $post_content;}但是在執行 preg_match 之前翻轉所有括號很容易,或者我假設應該很容易讓 preg_match 考慮到這一點。
查看完整描述

2 回答

?
慕容3067478

TA貢獻1773條經驗 獲得超3個贊

不要使用正則表達式來解析 HTML。


您有一個簡單的目標:將文本內容限制為給定的字數,確保 HTML 保持有效。


為此,我建議循環遍歷文本節點,直到您計算出一定數量的單詞,然后刪除之后的所有內容。


$dom = new DOMDocument();

$dom->loadHTML($post_content);

$xpath = new DOMXPath($dom);

$all_text_nodes = $xpath->query("//text()");

$words_left = 48;

foreach( $all_text_nodes as $text_node) {

    $text = $text_node->textContent;

    $words = explode(" ", $text); // TODO: maybe preg_split on /\s/ to support more whitespace types

    $word_count = count($words);

    if( $word_count < $words_left) {

        $words_left -= $word_count;

        continue;

    }

    // reached the threshold

    $words_that_fit = implode(" ", array_slice($words, 0, $words_left));

    // If the above TODO is implemented, this will need to be adjusted to keep the specific whitespace characters

    $text_node->textContent = $words_that_fit;


    $remove_after = $text_node;

    while( $remove_after->parentNode) {

        while( $remove_after->nextSibling) {

            $remove_after->parentNode->removeChild($remove_after->nextSibling);

        }

        $remove_after = $remove_after->parentNode;

    }

    break;

}

$output = substr($dom->saveHTML($dom->getElementsByTagName("body")->item(0)), strlen("<body>"), -strlen("</body>"));


查看完整回答
反對 回復 2023-04-28
?
喵喵時光機

TA貢獻1846條經驗 獲得超7個贊

好的,我想出了一個解決方法。我不知道這是否是最優雅的解決方案,所以如果有人看到更好的解決方案,我仍然很想聽聽,但現在我意識到我不必在我正在搜索的字符串中實際包含 html確定切割的位置,我只需要它是相同的長度。我抓取了所有的 html 元素,并創建了一個虛擬字符串,用相同數量的星號替換了所有元素:


// create faux string with placeholders instead of html for search purposes

preg_match_all('/<\/?[^>]*>/', $post_content, $alltags_result);

$tagcount = count( $alltags_result );

$post_content_dummy = $post_content;

foreach($alltags_result[0] as $thistag){

    $post_content_dummy = str_replace($thistag, str_repeat("*",strlen($thistag)), $post_content_dummy);

}

然后我只是$post_content_dummy在 while 循環中使用而不是$post_content,以便找到切割位置,然后$post_content進行實際切割。到目前為止似乎工作正常。


查看完整回答
反對 回復 2023-04-28
  • 2 回答
  • 0 關注
  • 170 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號