HTML文本中移除所有HTML標記并提取純文本是我們經常需要使用的文本內容處理方式,比如搜索引擎、網站爬蟲或者本地文檔檢索系統需要提取網頁或HTML文檔的實際內容進行索引。通過去除HTML標簽,可以專注于實際的文字信息,提高搜索結果的相關性和準確性。在新聞聚合應用或社交媒體平臺上展示網頁鏈接的摘要時,通常會提取并顯示純文本內容以提供簡潔的預覽。對于視覺障礙人士使用的輔助技術如屏幕閱讀器,它們無法解析復雜的HTML結構,因此需要提取純文本以便朗讀給用戶。所以今天給大家分享一個使用正則表達式移除所有的Html標記的方法,供有需要的朋友們參考:
第一個核心代碼是:正則表達式"<.*?>"
// 示例用法:
string inputHtml = "<html><body><h1>Hello, World!</h1>This is a <b>test</b>.</body></html>";
string plainText = RemoveHtmlTags(inputHtml);
Console.WriteLine(plainText); // 輸出: "Hello, World!This is a test."
public static string RemoveHtmlTags(string html)
{
// 正則表達式用于匹配HTML標簽
Regex regex = new Regex("<.*?>", RegexOptions.Singleline | RegexOptions.Compiled);
// 使用正則表達式的Replace方法移除所有匹配的HTML標簽
string result = regex.Replace(html, String.Empty);
return result;
}
這個正則表達式<.*?>是非貪婪匹配任何以 < 開始、以 > 結束的字符串,它會盡可能少地匹配字符以找到每個HTML標簽。
請注意,雖然此方法對于簡單場景可能有效,但對復雜的HTML文檔(特別是含有嵌套標簽、注釋、CDATA等內容)可能不夠健壯,因為它無法處理所有可能的HTML結構。
第二個核心代碼是:正則表達式"<[^>]*>"
public static string ExtractPlainTextFromHtml(string html)
{
// 使用正則表達式匹配所有的HTML標簽
// 注意:這個簡單的正則表達式適用于大多數基礎HTML結構,但可能無法處理復雜嵌套或特殊格式的HTML
Regex regex = new Regex("<[^>]*>", RegexOptions.Singleline | RegexOptions.Compiled);
// 使用Replace方法去除所有匹配到的HTML標簽,并返回純文本內容
string plainText = regex.Replace(html, String.Empty);
return plainText.Trim(); // 為了得到更整潔的結果,可以對結果進行trim操作以去除多余的空白字符
}
在這段代碼中,我們定義了一個名為ExtractPlainTextFromHtml的方法,該方法利用正則表達式 <[^>]*> 來查找并替換所有HTML標簽。這里的正則表達式表示任何以 < 開始、以 > 結束的非空字符串(即HTML標簽),Singleline 選項使.能匹配換行符,以便跨多行搜索標簽,而 Compiled 選項則是為了優化正則表達式的性能。
第二個核心代碼是:正則表達式"<[^>]*>"
public static string RemoveHtmlTags(string html)
{
// 正則表達式,匹配所有HTML標簽
string pattern = "<[^>]+>";
// 使用Regex.Replace方法移除所有匹配的HTML標簽
return Regex.Replace(html, pattern, String.Empty);
}
請注意,此方法僅移除HTML標記,不會解析或處理嵌入在HTML中的JavaScript代碼或其他非標記內容。此外,此方法也無法處理不規范或不符合預期格式的HTML標記。如果需要更復雜的HTML解析或清理,您可能需要使用專門的HTML解析庫,如AngleSharp或HtmlAgilityPack等。
盡管上述方法對于許多簡單場景已經足夠有效,但在面對復雜的HTML文檔時,由于HTML本身的嵌套和特殊結構,簡單的正則表達式可能無法完美地解析并移除所有標簽。在這種情況下,推薦使用專門為處理HTML設計的庫,如HtmlAgilityPack,它可以準確地解析HTML并提供豐富的API用于提取純文本內容。
今年國慶假期終于可以憋在家里了不用出門了,不用出去看后腦了,真的是一種享受。這么好的光陰怎么浪費,睡覺、吃飯、打豆豆這怎么可能(耍多了也煩),完全不符合我們程序員的作風,趕緊起來把文章寫完。
這篇文章比較基礎,在國慶期間的業余時間寫的,這幾天又完善了下,力求把更多的前端所涉及到的關于文件上傳的各種場景和應用都涵蓋了,若有疏漏和問題還請留言斧正和補充。
以下是本文所涉及到的知識點,break or continue ?
原理很簡單,就是根據 http 協議的規范和定義,完成請求消息體的封裝和消息體的解析,然后將二進制內容保存到文件。
我們都知道如果要上傳一個文件,需要把 form 標簽的enctype設置為multipart/form-data,同時method必須為post方法。
那么multipart/form-data表示什么呢?
multipart互聯網上的混合資源,就是資源由多種元素組成,form-data表示可以使用HTML Forms 和 POST 方法上傳文件,具體的定義可以參考RFC 7578。
multipart/form-data 結構
看下 http 請求的消息體
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次請求要上傳文件,其中boundary表示分隔符,如果要上傳多個表單項,就要使用boundary分割,每個表單項由———XXX開始,以———XXX結尾。
每一個表單項又由Content-Type和Content-Disposition組成。
Content-Disposition: form-data 為固定值,表示一個表單元素,name 表示表單元素的 名稱,回車換行后面就是name的值,如果是上傳文件就是文件的二進制內容。
Content-Type:表示當前的內容的 MIME 類型,是圖片還是文本還是二進制數據。
解析
客戶端發送請求到服務器后,服務器會收到請求的消息體,然后對消息體進行解析,解析出哪是普通表單哪些是附件。
可能大家馬上能想到通過正則或者字符串處理分割出內容,不過這樣是行不通的,二進制buffer轉化為string,對字符串進行截取后,其索引和字符串是不一致的,所以結果就不會正確,除非上傳的就是字符串。
不過一般情況下不需要自行解析,目前已經有很成熟的三方庫可以使用。
至于如何解析,這個也會占用很大篇幅,后面的文章在詳細說。
使用 form 表單上傳文件
在 ie時代,如果實現一個無刷新的文件上傳那可是費老勁了,大部分都是用 iframe 來實現局部刷新或者使用 flash 插件來搞定,在那個時代 ie 就是最好用的瀏覽器(別無選擇)。
DEMO
這種方式上傳文件,不需要 js ,而且沒有兼容問題,所有瀏覽器都支持,就是體驗很差,導致頁面刷新,頁面其他數據丟失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
選擇文件:
<input type="file" name="f1"/> input 必須設置 name 屬性,否則數據無法發送<br/>
<br/>
標題:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 傳</button>
</form>
復制代碼
服務端文件的保存基于現有的庫koa-body結合 koa2實現服務端文件的保存和數據的返回。
在項目開發中,文件上傳本身和業務無關,代碼基本上都可通用。
在這里我們使用koa-body庫來實現解析和文件的保存。
koa-body 會自動保存文件到系統臨時目錄下,也可以指定保存的文件路徑。
然后在后續中間件內得到已保存的文件的信息,再做二次處理。
NODE
/**
* 服務入口
*/
var http = require('http');
var koaStatic = require('koa-static');
var path = require('path');
var koaBody = require('koa-body');//文件保存庫
var fs = require('fs');
var Koa = require('koa2');
var app = new Koa();
var port = process.env.PORT || '8100';
var uploadHost= `http://localhost:${port}/uploads/`;
app.use(koaBody({
formidable: {
//設置文件的默認保存目錄,不設置則保存在系統臨時目錄下 os
uploadDir: path.resolve(__dirname, '../static/uploads')
},
multipart: true // 開啟文件上傳,默認是關閉
}));
//開啟靜態文件訪問
app.use(koaStatic(
path.resolve(__dirname, '../static')
));
//文件二次處理,修改名稱
app.use((ctx) => {
var file = ctx.request.files.f1;//得道文件對象
var path = file.path;
var fname = file.name;//原文件名稱
var nextPath = path+fname;
if(file.size>0 && path){
//得到擴展名
var extArr = fname.split('.');
var ext = extArr[extArr.length-1];
var nextPath = path+'.'+ext;
//重命名文件
fs.renameSync(path, nextPath);
}
//以 json 形式輸出上傳文件地址
ctx.body = `{
"fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
}`;
});
/**
* http server
*/
var server = http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ...... ');
復制代碼
CODE
https://github.com/Bigerfe/fe-learn-code/
近在抓取一些比較有價值的網站資源,用于訓練AI寫作系統,保證AI能在我采集的龐大數據庫中學會利用一個命題就可以創作高質量原創文章。對!我說的是原創文章,不是偽原創。至于這個AI寫作的系統將會在我成功后與大家展開更為細致的分享,今天我們的主題是,如何通過火車頭采集器批量采集網站文章。
軟件:火車頭采集器/高鐵采集器
使用環境:PC端
進入待采集網站,打開需要采集的欄目或者待采集的關鍵詞搜索列表。
待采集網頁
確定這個欄目的文章頁數,翻到底部發現總頁數為15,確定采集頁數為15。
網站頁碼位置
;跳轉到下一頁,確定網頁的起始網址格式,變量基本是.html前面的序號,所以我們先直接復制下來。
進入高鐵采集器,點擊+按鈕跳出任務設置頁面。
高鐵采集器/火車頭采集器
點擊網頁采集規則頁面的起始網頁右邊的第一個按鈕進入向導,填入復制下來的頁面地址,并將頁面的變量替換成右邊的地址參數,直接刪掉原頁碼然后點擊按鈕插入就可以。
網址采集規則
最終會自動生成一個采集列表文章的鏈接,但這只是采集頁面數據,并沒有將需要的內容精確地采集到。
采集起始網址
因為需要讓機器知道我們要采集哪些數據,所以我們要在網頁代碼中找到開頭和結尾的標志,以便機器采集。
右擊網頁空白處查看網頁源代碼
查看頁面源代碼
由于源碼大多是一行顯示,所以我們需要勾選源碼頂部的“換行”復選框。
勾選換行復選框
Ctrl+F 搜索源代碼中包含列表頁的第一條數據的標題,并尋找與該標題臨近的一個唯一標簽。
查找是否唯一
<h1><span>產品運營</span></h1> </div> <div class="sec-panel-body">
在這段代碼中,我選擇了 “<divclass="sec-panel-body">” 作為識別開頭的代碼。
同樣的方式,我搜尋列表頁的最后一條數據的標題,找到了識別結尾的代碼。
是否是唯一且能識別到的代碼,我們也可以通過 Ctrl+F 去查找,只要搜索數據是唯一的就是了。
填寫起始代碼
填入寫好的起始和結束代碼后,點擊右下角的網頁測試按鈕測試采集數據是否正常。
測試是否能采集到需要的網址
讓機器采集一部分列表頁數據就可以停止了,然后看到采集的數據是比較多的,有些數據不是我們需要的數據頁,所以我們需要將其排除。
查閱到內容頁的地址為/n/(*).html,所以我們可以用網頁格式去鎖定采集地址。
確定地址欄規則
在鏈接過濾處選擇鏈接包含并填入剛才的格式
過濾不需要的鏈接
接下來發現內容頁地址采集正常。
正確獲取需要的地址
接下來我們就需要寫內容頁的采集規則,這里比較復雜,需要認真看。在最近的測試中,發現對于新手來說也并不是難事,因為邏輯一樣的,多去調試就行了。
進入內容采集規則頁面,內置有標題和內容,這里我多加兩條數據“作者”和“日期”,以便大家更深理解。
內容采集規則
我們在采集過程中可能需要更多的數據,基本上都可以按照我說的操作采集出來。
同樣,在文章頁面右擊調出源代碼,我按標題、作者、時間、內容的順序教大家寫采集規則。
首先,我們查找到文章標題的位置,確定位置在<h1>標簽內,其實大部分的頁面都是<h>標簽,只是里面的樣式不同而已。
找到標題位置
<h1 class="entry-title">標題</h1>
接著直接看后面的代碼,通過一些標志,看到作者和時間,這時候就確定了時間和地址。
找到作者和日期位置
<a class="nickname url fn j-user-card">作者</a> </span> <span class="dot">?</span> <time class="entry-date published" datetime="2022-10-31T08:17:06+08:00" pubdate> 2022年10月31日 08:17:06 </time>
然后再看接下來的內容,去找找內容的代碼。
通過文章內容找到旁邊的div標簽是唯一識別的標簽(經驗之談,一般在class中包含content),咱們就可以確定內容的開始標簽。
找到內容位置
<div class="entry-content text-indent">
同樣的方法,找到結尾詞旁邊的標簽為:
<div class="entry-readmore">
這就確定了標題、作者、時間、內容了,接下來需要去軟件內寫清楚規則。
我們提取標題優先選擇正則提取,并將復制的所有變量在匹配內容中用[參數]代替,在組合結果中直接點擊[參數1]。
設置標題提取規則
同樣我也選擇用正則提取,由于某些數據是變量且不需要,我們直接用(*)代替即可,需要的內容用[參數]替代,并在組合結果中選擇[參數1]。
設置作者提取規則
因為我想給大家講一下為什么有[參數1]、[參數2]、[參數N],所以我使用多個參數進行舉例。
在這里,我把標簽中的參數作為我的結果,將標簽中的內容直接丟掉了,但是獲取的結果是一樣的。
設置日期提取規則
所以在寫規則的時候也不一定要中規中矩按別人教你的來,只要保證數據準確就行。
④內容 這里不需要多說,因為前面我們分析過,前后截取的代碼已經知道,直接填進去。
設置內容提取規則
但是要考慮到不同頁面中的開頭和結尾可能是變量,所以我們要多打開一些文章去查看網頁代碼,畢竟某些頁面開頭有引言,有的結尾有版權聲明。
現在規則寫好了,我們需要找個頁面測試下,我們發現數據采集是正確的,現在基本的采集就完成了。
找幾個頁面測試下
對于我來說,AI寫作訓練不需要標簽,所以我需要在采集的時候直接過濾掉,所以我在內容標簽下的數據處理中,選擇html標簽過濾,直接全選了所有標簽。為了閱讀方便,我取消了換行和所有標簽,當然我們也可以通過對數據的處理輸出我們需要的內容。
html標簽過濾
html標簽過濾
我們不設置內容發布規則的話,會導致文章采集了無法輸出。
由于我只需要將數據輸出為文檔供AI學習,包括web在線發布和導入數據庫都包含比較復雜的對應關系,所以輸出這里我只講保存本地文件這一項。
內容發布規則
我們將本地文件保存打開,以txt文件格式輸出為例,我們選擇txt,并設置保存位置為自定義位置,文件模板我使用的是:
文章格式
把它保存為txt文件,并將文件模板選擇為這個文件,軟件就會按照這個格式去輸出文章了。
所有設置都配置好了之后就直接保存并退出,然后進入主頁面,勾選任務右邊的“采網址”、“采內容”、“發布”復選框,右擊任務并選擇開始即可,如果看到運行日志中運行正常就可以讓它靜默采集了,如果有提示錯誤,分析錯誤產生原因,然后對癥下藥就行了。
直接采集并發布
以下是輸出的案例:
采集到的內容
我們在采集中一定不會像我說得這么簡單,所以我把我遇到的坑提前告知大家,以免大家走彎路。
采集的數據為空白有一部分原因是原文就是空白的,比如網頁上面的問答,如果沒有回答,他的內容就是空的。還有就是采集規則不適用于所有頁面,重新制定新的規則,保證所有數據能夠輸出為止。
有時候我們采集的數據是全空,這大概率是因為網速問題或者是網站問題,重新采集即可,因為沒有采集到的數據會標注未采和未發。
由于某篇文章在不同的標簽或者板塊下,軟件不會直接幫你過濾,但是我們可以通過設置標簽下的內容過濾,勾選“采集內容不得為空重復”的按鈕。(勾選“采集內容不得為空”也可以解決問題1)
內容過濾
這里我們在采集后會發現有很多版權詞或者一些需要過濾的詞,不必重新設置采集規則,而是在本地數據中,選擇所有數據,并對特定標簽中的特定內容直接進行替換或者過濾即可。
替換內容
以上原創教程僅用于學術交流,請勿搬運或用于不法用途,大佬請直接關閉本文。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。