Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
何提升Web頁面的性能,很多開發人員從多個方面來下手如JavaScript、圖像優化、服務器配置,文件壓縮或是調整CSS。
很顯然HTML 已經達到了一個瓶頸,盡管它是開發Web 界面必備的核心語言。HTML頁面的負載也是越來越重。大多數頁面平均需要40K的空間,像一些大型網站會包含數以千計的HTML 元素,頁面Size會更大。
如何有效的降低HTML 代碼的復雜度和頁面元素的數量,本文主要解決了這個問題,從多個方面介紹了如何編寫簡練,清晰的HTML 代碼,能夠使得頁面加載更為迅速,且能在多種設備中運行良好。
在設計和開發過程中需要遵循以下原則:
HTML,CSS 和JavaScript三者的關系
HTML 是用于調整頁面結構和內容的標記語言。HTML 不能用于修飾樣式內容,也不能在頭標簽中輸入文本內容,使代碼變得冗長和復雜,相反使用CSS 來修飾布局元素和外觀比較合適。HTML元素默認的外觀是由瀏覽器默認的樣式表定義的,如在Chrome中h1標簽元素會渲染成32px的Times 粗體。
三條通用設計規則:
文檔結構方面也可以做優化,如下:
<!DOCTYPE html> <html> <head> <title>Recipes: pesto</title> </head> <body> <h1>Pesto</h1> <p>Pesto is good!</p> </body> </html>
<head> <title>My pesto recipe</title> <link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="css/local.css"> </head>
使用這兩種方法,瀏覽器會在解析HTML代碼之前將CSS信息準備好。因此有助于提升頁面加載性能。
在頁面底部body結束標簽之前輸入JavaScript代碼,這樣有助于提升頁面加載的速度,因為瀏覽器在解析JavaScript代碼之前將頁面加載完成,使用JavaScript會對頁面元素產生積極的影響。
<body> ... <script src="/js/global.js"> <script src="js/local.js"> </body>
使用Defer和async屬性,腳本元素具有async 屬性無法保證會按順序執行。
可在JavaScript代碼中添加Handlers。千萬別加到HTML內聯代碼中,比如下面的代碼則容易導致錯誤且不易于維護:
index.html:
<head> ... <script src="js/local.js"> </head> <body onload="init()"> ... <button onclick="handleFoo()">Foo</button> ... </body>
下面的寫法比較好:
index.html:
<head> ... </head> <body> ... <button id="foo">Foo</button> ... <script src="js/local.js"> </body>
js/local.js:
init(); var fooButton = document.querySelector('#foo'); fooButton.onclick = handleFoo();
驗證
優化網頁的一種方法就是瀏覽器可處理非法的HTML 代碼。合法的HTML代碼很容易調試,且占內存少,耗費資源少,易于解析和渲染運行起來更快。非法的HTML代碼讓實現響應式設計變得異常艱難。
當使用模板時,合法的HTML代碼顯得異常重要,經常會發生模板單獨運行良好,當與其他模塊集成時就報各種各樣的錯誤,因此一定要保證HTML代碼的質量,可采取以下措施:
代碼格式
格式一致性使得HTML代碼易于閱讀,理解,優化,調試。
語義標記
語義指意義相關的事物,HTML 可從頁面內容中看出語義:元素和屬性的命名一定程度上表達了內容的角色和功能。HTML5 引入了新的語義元素,如<header>,<footer>及<nav>。
選擇合適的元素來編寫代碼可保證代碼的易讀性:
例如:
<div>Name: <input type="text" id="name"></div>
換種寫法會更好:
1: <div> 2: <label for="name">Name:</label><input type="text" id="name"> 3: </div>
布局
要提高HTML代碼的性能,要遵循HTML 代碼以實現功能和為目標,而不是樣式。
CSS
雖然本文講解的是如何優化HTML,下面介紹了一些使用css的基本技能:
以上就是本文介紹的優化HTML代碼的技巧,一個高質量高性能的網站,往往取決于對細節的處理,因此我們在日常開發中,能夠考慮到用戶體驗,后期維護等方面,則會產生更高效的開發。
在學習和工作中,我們經常需要使用日志來記錄程序的運行狀態和調試信息。而為了更好地區分不同的日志等級,我們可以使用不同的顏色來呈現,使其更加醒目和易于閱讀。
在下圖運行結果中,我們使用了 colorlog 庫來實現彩色日志輸出。通過定義不同日志等級對應的顏色,我們可以在控制臺中以彩色的方式顯示日志信息。例如,DEBUG 級別的日志使用白色,INFO 級別的日志使用綠色,WARNING 級別的日志使用黃色,ERROR 級別的日志使用紅色,CRITICAL 級別的日志使用藍色。
但是在查看日志文件時,我們會發現日志信息是系統默認的字體顏色,并且前后多了一些特殊符號,例如 [32m 等。這是因為在控制臺中使用的是 ANSI 轉義序列來實現彩色文本效果,而這些特殊符號是 ANSI 轉義序列的一部分。如下圖所示:
現在有一個需求,在前端頁面直接查看日志內容并還原彩色文本效果,因此,我們將進行以下內容講解:
本文代碼點擊此處跳轉,往期系列文章請訪問博主的 項目實戰專欄,博文中的所有代碼全部收集在博主的 GitHub 倉庫中;
ANSI 轉義序列是美國國家標準化組織(American National Standards Institute,ANSI)制定的標準,是一種用于控制文本終端顯示的特殊字符序列。它們以 3[ 開頭,以字母和數字組合的形式表示不同的控制功能。
ANSI 轉義序列可以用于控制文本的顏色、背景色、文本樣式(如粗體、斜體等)、光標位置、清屏等操作。通過在輸出文本中插入適當的 ANSI 轉義序列,可以實現豐富的終端顯示效果。
以下是一些常用的 ANSI 轉義序列示例:
需要注意的是,ANSI 轉義序列在不同的終端和操作系統上的支持程度可能會有所不同。在某些終端中,可能無法正確解釋和顯示 ANSI 轉義序列。
我們以 3[31m 和 3[42m 為例,輸出一個綠底紅字的句子 Hello World! --sidiot.,代碼如下所示:
log.debug("3[42m3[31mHello World! --sidiot.3[0m3[0m")
運行結果:
這里的話,我們使用 Python 的 http.server 模塊來啟動一個簡單的 HTTP 服務器。
比較快捷的方式就是在日志文件夾中打開終端,輸入 python -m http.server 8888 即可,運行結果如下所示:
不過這種方式相對來說還是不太安全的,因此我們可以通過設置白名單的方式,來規避一些潛在的安全隱患,代碼如下所示:
import http.server
import socketserver
class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def check_client_address(self):
# 設置白名單,只允許特定的IP地址或主機訪問
whitelist = ['127.0.0.1', 'localhost']
client_address = self.client_address[0]
if client_address not in whitelist:
self.send_response(403)
self.end_headers()
self.wfile.write(b'Forbidden. Please contact sidiot.')
return False
return True
def do_GET(self):
if not self.check_client_address():
return
super().do_GET()
with socketserver.TCPServer(('0.0.0.0', 8888), HTTPRequestHandler) as httpd:
httpd.serve_forever()
目前本機的 IP 為 192.168.124.23,當我們以 127.0.0.1 來訪問 8888 服務端口時,訪問是成功的,但是當我們用 192.168.124.23 來訪問服務端口時,訪問是失敗的。
運行結果:
現在我們點擊文件,它會直接通過瀏覽器直接下載,但是我們需要的是在網頁上能夠直接閱覽文件中的內容,因此我們可以從 do_GET() 下手。
我們可以設計一個根據傳入的文件名參數,讀取本地文件并作為響應結果進行返回的方法,然后根據一定的規則進行觸發,代碼如下所示:
def read_file(self):
try:
self.send_response(200)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write(open(self.path[6:], 'rb').read())
except FileNotFoundError:
self.send_response(404)
self.end_headers()
self.wfile.write(b'File not found!')
def do_GET(self):
if self.check_client_address():
if self.path.startswith("/?log="):
self.read_file()
else:
super().do_GET()
上述代碼通過檢查請求的資源路徑來處理 GET 請求。如果請求的資源路徑前綴是 /?log=,且是當前目錄下存在的日志文件,它會讀取文件并將其內容作為響應發送。否則,它會使用基類的默認行為處理普通的 GET 請求。
運行結果:
至此,我們已經實現了前端頁面直接查看日志內容的功能。
原理分析
當我們想要在前端頁面展示 ANSI 字體的彩色效果時,我們只需要簡單地將 ANSI 轉義序列轉換成相應的 HTML 代碼就可以實現了。這個轉換過程實際上可以通過編寫一個 Python 函數來實現,該函數可以接受包含 ANSI 控制碼的字符串作為輸入,并將其轉換為帶有相應樣式的 HTML 代碼輸出,代碼如下所示:
def convert_ansi_to_html(ansi_text):
ansi_to_html = {
'\x1b[31m': '<span style="color: red;">',
'\x1b[42m': '<span style="background-color: green;">',
...,
}
html_text = re.sub(r'\x1b[[0-9;]*m', lambda match: ansi_to_html.get(match.group(0), ''), ansi_text)
return html_text
if __name__ == '__main__':
ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(ansi)
html = convert_ansi_to_html(ansi)
print(f"convert content: {html}")
需要注意的是,在 ANSI 轉義序列中,\x1b 和 3 都代 表ASCII 碼中的 Escape 字符,用于開始一個轉義序列。
運行結果:
使用 ansiconv 轉換
接下來,我們借助已有的庫函數 ansiconv 進行 ANSI 的轉換。
通過 pip 進行安裝:
pip install ansiconv
根據 ansiconv 的官方文檔使用其中的三個方法 to_plain(),to_html() 和 base_css() 來實現在前端頁面展示 ANSI 字體的彩色效果,代碼如下所示:
import ansiconv
ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(f"Ansi: {ansi}")
plain = ansiconv.to_plain(ansi)
html = ansiconv.to_html(ansi)
print(f"Convert Plain: {plain}")
print(f"Convert HTML: {html}")
在 base_css() 中會有相關的 CSS 映射表,如下所示:
css_rule('.ansi31', color="#FF0000"),
css_rule('.ansi42', background_color="#00FF00"),
運行結果:
研究 ansiconv 源碼
我們將通過研究 ansiconv 的源碼,以便深入了解它是如何將 ANSI 轉換成純文本或 HTML 代碼的工作原理。
to_plain() 的源碼如下所示:
上述代碼使用正則表達式匹配字符串中的 ANSI 轉義序列,并將其替換為空字符串,從而得到不包含轉義序列的純文本。
正則表達式的含義如下:
我們通過 re.findall() 方法來獲取所有匹配的結果,這樣夠清晰地捕獲所有符合條件的匹配項,從而更好地理解 ansiconv 是如何進行 ANSI 到純文本的轉換,代碼如下所示:
ansi = "\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m"
print(re.findall(r'\x1B[[0-9;]*[ABCDEFGHJKSTfmnsulh]', ansi))
運行結果:
to_html() 的源碼如下所示:
上述代碼將 ANSI 字符串分割成塊,并對每個塊調用 _block_to_html() 函數進行解析和轉換,同時還處理了 ANSI 命令 "A",模擬向上移動光標的行為。如果 replace_newline 為 True,則 HTML 字符串中的換行符 \n 將替換為 <br />\n 以保留 HTML 輸出中的換行符。
其中 _block_to_html() 的源碼如下所示:
上述代碼使用正則表達式匹配 ANSI 代碼,并根據匹配結果生成對應的 HTML 代碼。
正則表達式的含義:
我們可以通過運行源碼里的部分代碼來幫助理解,代碼如下所示:
text = ("\x1B[0;32;45msidiot\n"
"\033[42m\033[31mHello World! --sidiot.\033[0m\033[0m")
print(text)
blocks = text.split('\x1B')
print(blocks)
for block in blocks:
match = re.match(r'^[(?P<code>\d+(?:;\d+)*)?(?P<command>[Am])', block)
if match is not None:
print("\nmatch:", match, ", code:", match.group('code'), ", command:", match.group('command'))
運行結果:
實際應用
通過深入理解 ANSI 轉換思路和 ansiconv 源碼,我們可以為之前的 http.server 服務帶來全新的優化。
首先,將原先的 read_file() 方法進行優化,代碼如下所示:
def read_file(self, content_type, file_io):
try:
self.send_response(200)
self.send_header("Content-Type", f"{content_type}; charset=utf-8")
self.end_headers()
self.wfile.write(file_io)
except FileNotFoundError:
self.send_response(404)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write(b'File not found!')
上述代碼通過接收 content_type 和 file_io 兩個參數,實現將自定義內容作為響應返回給客戶端。
然后修改請求路徑,使其能夠返回純文本和 HTML 兩種不同類型的內容,代碼如下所示:
def do_GET(self):
if self.check_client_address():
if self.path.startswith("/?plain="):
file = open(self.path[8:], 'rb').read()
plain = ansiconv.to_plain(file.decode('UTF-8'))
self.read_file("text/plain", plain.encode())
elif self.path.startswith("/?html="):
file = open(self.path[7:], 'rb').read()
conv = ansiconv.to_html(file.decode('UTF-8'))
css = ansiconv.base_css()
html = """
<html>
<head><style>{0}</style></head>
<body>
<pre class="ansi_fore ansi_back">{1}</pre>
</body>
</html>
""".format(css, conv)
print(html)
self.read_file("text/html", html.encode())
else:
super().do_GET()
這里要注意的是,需要設置 CSS 樣式,不然 class 類是無法進行渲染的。
純文本運行結果:
HTML 運行結果:
在本文中,我們探討了如何實現將 ANSI 字體在前端頁面進行彩色展示的方法。在前端頁面中直接顯示 ANSI 轉義序列是不起作用的,因為瀏覽器不會解析和處理這些轉義序列。
為了在前端頁面實現彩色展示,我們介紹了一種方法,即將 ANSI 轉義序列轉換為對應的 HTML 代碼。通過解析 ANSI 轉義序列并將其轉換為適當的 HTML 標簽和樣式,我們可以在前端頁面上還原彩色文本的效果。
在本文中,我們使用了 Python 中的 ansiconv 庫來實現 ANSI 轉換。該庫提供了 to_plain 和 to_html 兩個方法,分別用于將 ANSI 轉義序列轉換為純文本和 HTML 代碼。我們還展示了如何使用這些方法來轉換 ANSI 字符串,并在前端頁面上顯示轉換后的結果。
通過本文的介紹,讀者可以了解到如何在前端頁面實現彩色文本的展示,從而提升用戶體驗和可讀性。無論是在日志查看器、終端模擬器還是其他需要展示彩色文本的應用中,這種技術都能發揮重要作用。
以上就是 從終端到瀏覽器:實現 ANSI 字體在前端頁面的彩色展示 的所有內容了,希望本篇博文對大家有所幫助!歡迎大家持續關注我的博客,一起分享學習和成長的樂趣!?
作者:sidiot
鏈接:https://juejin.cn/post/7381820436274184202
html圖像
在htmtl中,圖像由<img>標簽定義.<img>是空標簽,它只包含屬性,并且沒有閉合標簽.
要在頁面上顯示圖像,使用源屬性(src).源屬性的值是圖像的url地址(統一資源定位符).
定義圖像的語法是:
<img src="url"/>
url指存儲圖像的位置.
<html>
<head>
<title>first page</title>
</head>
<body>
<img src="logo.png" alt=" "/>
</body>
<html>
●如果圖像無法顯示,則alt屬性用來為圖像定義一串預備的可替換的文本.alt屬性是必需的.
height(高度)與width(高度)屬性用于設置圖像的高度與寬度.該屬性值可以以像素或百分比形式指定,默認單位為像素
<html>
<head>
<title>first page</title>
</head>
<body>
<img src="logo.png" height="100px" width="100px" alt=" "/>
<!--或者-->
<img src="logo.png" height="80%" width="80%" alt=" "/>
</body>
</html>
●<img>的border屬性規定圖像周圍的邊框的寬度.默認情況下,圖像是沒有邊框的
border屬性的屬性值的單位是像素.表示邊框的寬度
實例:帶有2個像素粗邊框的圖像.
<img src="logo.png" height="100px" width="100px" border="2" alt=" " />
二 html鏈接
html使用標簽<a>來設置超文本鏈接.
超鏈接可以是一個字,一個詞,或者一組詞,也可以是一幅圖像,你可以點擊這些內容來跳轉到新的文檔或者當前文檔中的某個部分.
在標簽<a>中,使用href(hyper text reference)屬性來描述鏈接的目標地址
鏈接的html代碼很簡單.格式如下:
<a href="url">鏈接文本</a>
上邊的代碼顯示為:鏈接文本(鏈接文本下面有下劃線)
●使用target屬性,你可以規定在何處打開鏈接文檔.如果給target屬性賦值_blank,將使鏈接在新窗口或新選項卡中打開.
<a href="url" target="_blank">鏈接文本</a>
三 html列表
無序列表是一個項目的列表,此列項目使用粗體圓點(典型的小黑圓圈)進行標記
無序列表使用<ul>標簽,與<li>標簽一起使用(unordered list)
<ul>
<li>咖啡</li>
<li>茶</li>
<li>牛奶</li>
</ul>
瀏覽器顯示效果如下:
有序列表也是一列項目,列表項目使用數字進行標記.
有序列表始于<ol>標簽,每個列表項目始于<li>標簽.
<ol>
<li>咖啡</li>
<li>菜</li>
<li>牛奶</li>
</ol>
運行效果如下:
四 html表格
表格由<table>標簽定義.
每個表格均有若干行(由<tr>標簽定義,table row),每行被分割為若干單元格(由<td>標簽定義,table division)
下面是一個包含兩行兩列的表格:
<table border="2">
<tr>
<td>阿/td>
<td>平</td>
</tr>
<tr>
<td>加</td>
<td>油</td>
</tr>
</table>
運行效果:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。