隨意觀看
工具准備
- python3.6
- 正則表達式(別的語言思路一樣,容易借鑒)
python正則表達式:flags的應用
這里主要介紹一下re.compile(pattern[, flags])里面的flags用法
| 標識符 | 作用 |
|---|---|
| re.I | 忽略大小寫 |
| re.L | 表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴於當前環境 |
| re.M | 多行模式 |
| re.S | ' . '並且包括換行符在內的任意字符(注意:' . '不包括換行符) |
| re.U | 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依賴於 Unicode 字符屬性數據庫 |
特別強調re.I和re.S的用法
- 眾所周知,html標簽是大小寫不敏感的,所以我們需要
re.I - 其次html中
<style>..</style>、<sript>..</scipt>等一些標簽里面是包含換行符的。而我們為了保留原來文本的特點包括換行符,所以需要re.S。讓.可以匹配換行符
清洗全角和半角字符
實現字符的清洗工作,否則,jieba詞庫會將全角數字全部分開。而且,清洗后的半角文本更適合觀看
小姿勢
中文文字永遠是全角,只有英文字母、數字鍵、符號鍵才有全角半角的概念,一個字母或數字占一個漢字的位置叫全角,占半個漢字的位置叫半角
全角半角轉換說明
- 全角字符unicode編碼從65281~65374 (十六進制 0xFF01 ~ 0xFF5E)
- 半角字符unicode編碼從33~126 (十六進制 0x21~ 0x7E)
- 空格比較特殊,全角為 12288(0x3000),半角為 32(0x20)
代碼實現
def Q2B(_char):#全角轉半角
if 65281<=ord(_char)<=65374:
_char = chr(ord(_char)-65248)
elif ord(_char)==12288:
_char = chr(32)
return _char
def isQ(Char):
return True if (65281<=ord(Char)<=65374 or ord(Char)==12288) else False
def B2Q(_char):#半角轉全角
if 33<=ord(_char)<=126:
_char = chr(ord(_char)+65248)
elif ord(_char)==32:
_char = chr(12288)
return _char
def isB(Char):
return True if (33<=ord(Char)<=126 or ord(Char)==32) else False
網頁字符實體
標准的html代碼中的文本內容是不會出現'<'/' '等這些字符的。現在很多工具都會將網頁文本內容處理成標准形式再發布。我們這里討論的就是標准的html代碼及文本內容
html字符實體查詢地址
為了方便討論,我們這里取了幾個常用的作為示范,並且構造以下dict
html_char = {}
html_char['"'] = html_char['"']='"'
html_char['''] = html_char['''] = "'"
html_char['&'] = html_char['&'] = '&'
html_char['<'] = html_char['<'] = '<'
html_char['>'] = html_char['>'] = '>'
html_char[' '] = html_char[' ']= ' '
Code實現
難點重點就在這里,做了很多准備工作,幸好python比較方便,其他語言的玩家可以借鑒一下思路
正則Code實現去標簽[1]
...
#CDATA 部分由 "<![CDATA[" 開始,由 "]]>" 結束:
cdata_rule = re.compile(r'<![CDATA[.*]]>',re.I | re.S)
#去除腳本(隨時會出現)
script_rule = re.compile(r'<script.*?</script>',re.I | re.S)
#取出<head>..</head>和中間的內容,style也在里面,不需要再寫了
head_rule = re.compile(r'<head.*?/head>',re.I | re.S)
#為了以防一些文本不是全部截取html代碼,還是寫一下以防萬一
style_rule = re.compile(r'<style.*?/style>',re.I | re.S)
#處理注釋
comment_rule = re.compile(r'<!.*?>',re.I | re.S)
#處理換行
br_rule = re.compile(r'<br\s*?/{0,1}>',re.I)
#html標簽
html_rule = re.compile(r'<.*?/{0,1}>',re.I)
...
正則Code實現去字符實體
...
global html_char
letter_char = re.compile(r'&[a-z]+;',re.I)
for char in letter_char.findall(raw):
raw = re.sub(char,html_char[char],raw)
number_char = re.compile(r'&#\d+;',re.I)
for char in number_char.findall(raw):
raw = re.sub(char,html_char[char],raw)
...
全部代碼(含測試文本)
import re
html_char = {}
html_char['"'] = html_char['"']='"'
html_char['''] = html_char['''] = "'"
html_char['&'] = html_char['&'] = '&'
html_char['<'] = html_char['<'] = '<'
html_char['>'] = html_char['>'] = '>'
html_char[' '] = html_char[' ']= ' '
def Q2B(_char):#全角轉半角
if 65281<=ord(_char)<=65374:
_char = chr(ord(_char)-65248)
elif ord(_char)==12288:
_char = chr(32)
return _char
def isQ(Char):
return True if (65281<=ord(Char)<=65374 or ord(Char)==12288) else False
def B2Q(_char):#半角轉全角
if 33<=ord(_char)<=126:
_char = chr(ord(_char)+65248)
elif ord(_char)==32:
_char = chr(12288)
return _char
def isB(Char):
return True if (33<=ord(Char)<=126 or ord(Char)==32) else False
#定義一個裝飾器,可有可無
def log(clean_html):
def info(*args, **kw):
print("The text after processing:")
return clean_html(*args, **kw)
return info
@log
def clean_html(html_str,special_char=None,to_char=None):
#這里留個接口,處理特殊字符串
if special_char:
special_rule = re.compile('|'.join(set(special_char)))
if not to_char:
to_char = ''
#CDATA 部分由 "<![CDATA[" 開始,由 "]]>" 結束:
cdata_rule = re.compile(r'<![CDATA[.*]]>',re.I | re.S)
#去除腳本(隨時會出現)
script_rule = re.compile(r'<script.*?</script>',re.I | re.S)
#取出<head>..</head>和中間的內容,style也在里面,不需要再寫了
head_rule = re.compile(r'<head.*?/head>',re.I | re.S)
#為了以防一些文本不是全部截取html代碼,還是寫一下以防萬一
style_rule = re.compile(r'<style.*?/style>',re.I | re.S)
#處理注釋
comment_rule = re.compile(r'<!.*?>',re.I | re.S)
#處理換行
br_rule = re.compile(r'<br\s*?/{0,1}>',re.I)
#html標簽
html_rule = re.compile(r'<.*?/{0,1}>',re.I)
if special_char:
raw = special_rule.sub(to_char,html_str)
else:
raw = html_str
raw = cdata_rule.sub('',raw)
raw = script_rule.sub('',raw)
raw = head_rule.sub('',raw)
raw = style_rule.sub('',raw)
raw = comment_rule.sub('',raw)
raw = br_rule.sub('\n',raw)
raw = html_rule.sub('',raw)
global html_char
letter_char = re.compile(r'&[a-z]+;',re.I)
for char in letter_char.findall(raw):
raw = re.sub(char,html_char[char],raw)
number_char = re.compile(r'&#\d+;',re.I)
for char in number_char.findall(raw):
raw = re.sub(char,html_char[char],raw)
raw_list = list(raw)
for i in range(len(raw_list)):
if isQ(raw_list[i]):
raw_list[i] = Q2B(raw_list[i])
raw = ''.join(raw_list)
return raw
def test():
test_html = """
<div id="sidebar">
<div id="tools">
<h5 id="tools_example"><a href="/example/xmle_examples.asp"> XML 實例,特殊字符:15(處理之后應該沒有了)</a></h5>
<h5 id="tools_quiz"><a href="/xml/xml_quiz.asp"><XML 測驗></a></h5>
<h3>'vevev'</h3>
</div>
<div id="ad">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-3381531532877742";
/* sidebar-160x600 */
google_ad_slot = "3772569310";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
</div>
"""
print(clean_html(test_html,'】15'))
if __name__=='__main__':
test()
進一步
其他腳本引用
在python的其他程序中,可以直接from clean_html import clean_html進行方便的調用(假設這個腳本名字為clean_html.py)
完善
- 補充字符實體(可以用爬蟲爬下來,有空弄一下)
- html標簽可能因為前端框架不同而有所差異(雖然不大)。但是都有規律,如
<Vue>..</Vue>等,有規律,正則表達式就容易構建了
代碼備注以標明作用 ↩︎
