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 青青青青青免精品视频,中文字幕在线网,国产高清网站

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Windows 命令行:深入 Windows 控制臺(tái)

          迎來(lái)閱讀第三篇Windows 命令行系列文章。在這篇,我們開(kāi)始深入Windows 控制臺(tái)和命令行,它是什么,你可以用它可以做什么……和它不能做什么!

          系列文章:

          1. 命令行產(chǎn)生的背景
          2. Windows 命令行的發(fā)展
          3. 深入Windows命令行(本篇)

          在開(kāi)始開(kāi)發(fā)Windows NT操作系統(tǒng)的那時(shí)候,大概是1989年,那時(shí)候還沒(méi)有GUI(圖形化用戶界面),也沒(méi)有桌面操作系統(tǒng),只有最原始的全屏的命令行界面,類似于MS-DOS的可視化界面越來(lái)越重要!Windows GUI 開(kāi)始開(kāi)發(fā)的時(shí)候是在開(kāi)發(fā)團(tuán)隊(duì)需要開(kāi)發(fā)一個(gè)基于控制臺(tái)的應(yīng)用的背景下誕生的!Windows 控制臺(tái)是第一個(gè)Windows NT的GUI應(yīng)用,并且可以保證兼容運(yùn)行繼續(xù)使用已有的Windows應(yīng)用。

          Windows 控制臺(tái)最初的代碼到現(xiàn)在(2018年)已經(jīng)有30年的歷史……古老的東西,事實(shí)上,今天還有很多開(kāi)發(fā)者在使用它!

          控制臺(tái)程序能做什么?

          就像之前的文章說(shuō)的,終端的工作其實(shí)很簡(jiǎn)單:

          • 處理用戶輸入:
          • 可以支持的輸入設(shè)備包括鍵盤(pán)、鼠標(biāo)、觸摸板、筆等等。
          • 轉(zhuǎn)換輸入的數(shù)據(jù)到中間字符的或者ANSI/VT編碼格式
          • 發(fā)送字符數(shù)據(jù)到已連接的應(yīng)用程序或設(shè)備
          • 處理應(yīng)用程序輸出:
          • 允許從已連接的應(yīng)用程序輸出文本
          • 更新屏幕上面的顯示,基于應(yīng)用程序接受顯示(比如顯示文本,移動(dòng)光標(biāo),設(shè)置字體顏色等)
          • 系統(tǒng)協(xié)調(diào)處理:
          • 運(yùn)行處理作業(yè)請(qǐng)求
          • 管理設(shè)備和資源
          • 支持調(diào)整窗口尺寸、最大化窗口、最小化窗口等
          • 中斷請(qǐng)求或當(dāng)信道關(guān)閉或結(jié)束處理

          但是,Windows 控制臺(tái)能做的事情有些不同:

          深入Windows控制臺(tái)內(nèi)部

          Windows控制臺(tái)是一種傳統(tǒng)的Win32可執(zhí)行文件,雖然它最初是用“C”編寫(xiě)的,但隨著團(tuán)隊(duì)現(xiàn)代化和模塊化控制臺(tái)的代碼庫(kù),大部分代碼都已正在遷移到現(xiàn)代C++了。

          對(duì)于那些關(guān)心此類事物的人:許多人都在詢問(wèn)Windows是用C還是C++編寫(xiě)的。答案是 - 盡管NT是基于對(duì)象的設(shè)計(jì) - 像大多數(shù)操作系統(tǒng)一樣,Windows幾乎完全用C語(yǔ)言編寫(xiě)!為什么? C++在內(nèi)存占用和代碼執(zhí)行開(kāi)銷方面引入了開(kāi)銷。即使在今天,使用C++編寫(xiě)的代碼的其所隱藏的開(kāi)銷也會(huì)令人大吃一驚,但早在1990年代后期,此時(shí)內(nèi)存價(jià)格約為60$/MB(是的......每個(gè)MEGABYTE為60美元!)時(shí),vtable等隱藏機(jī)制的內(nèi)存開(kāi)銷非常高。此外,虛方法間接調(diào)用和對(duì)象解引用的開(kāi)銷可能導(dǎo)致當(dāng)時(shí)的C++代碼存在非常顯著的性能和規(guī)模損耗。雖然你仍然需要當(dāng)心,現(xiàn)代C++在現(xiàn)代計(jì)算機(jī)上的性能開(kāi)銷并不是一個(gè)值得關(guān)注的問(wèn)題,同時(shí)考慮到其安全性、可讀性和可維護(hù)性方面的優(yōu)勢(shì),這通常是一種可接受的折衷...這就是為什么我們將Console的代碼穩(wěn)步升級(jí)到現(xiàn)代C++這樣做的原因!

          那么,Windows 控制臺(tái)內(nèi)部是什么樣?

          在 Windows 7 之前,Windows 控制臺(tái)實(shí)例托管于核心的客戶-服務(wù)器運(yùn)行子系統(tǒng)(Client Server Runtime Subsystem,CSRSS)!然而,在 Windows 7 中,考慮到安全性和可靠性因素,控制臺(tái)從CSRSS 中剝離出來(lái),組件了一個(gè)包含如下二進(jìn)制文件的新家庭:

          • conhost.exe - 用戶模式的 Windows 控制臺(tái) UX 和命令行管道
          • condrv.sys - 一個(gè)提供基礎(chǔ)通信結(jié)構(gòu)的核心驅(qū)動(dòng),連接 conhost 和命令行 Shell/工具/應(yīng)用之間的通信

          控制臺(tái)當(dāng)前的內(nèi)部結(jié)構(gòu)總體結(jié)構(gòu)圖就像這樣:

          控制臺(tái)的核心組件包含如下內(nèi)容(自下而上):

          • ConDrv.sys - 核心模式驅(qū)動(dòng)
          • 請(qǐng)求執(zhí)行 API 調(diào)用控制臺(tái)實(shí)例的數(shù)據(jù)呈現(xiàn)
          • 從控制臺(tái)發(fā)送到命令行應(yīng)用的文本
          • 為控制臺(tái)及其連接的命令行應(yīng)用提供高性能通信通道
          • 在控制臺(tái)及附著于其上的命令行應(yīng)用這間反復(fù)傳遞 IO 控制 (IOCTL) 消息
          • 管理控制臺(tái) IOCTL 消息
          • ConHost.exe - Win32 圖形界面(GUI)應(yīng)用:
          • 管理控制臺(tái)容器在屏幕上的布局、大小、位置等。
          • 顯示并處理設(shè)置界面等。
          • 調(diào)用 Windows 消息隊(duì)列,處理 Windows 消息并將用戶輸入轉(zhuǎn)換為鍵盤(pán)和鼠標(biāo)事件,并將之存儲(chǔ)于輸入緩沖區(qū)。
          • API Server: 轉(zhuǎn)換 API 調(diào)用時(shí)從命令行應(yīng)用收到的 IOCTL 消息,并將文本記錄從控制臺(tái)發(fā)給命令行應(yīng)用。
          • API: 實(shí)現(xiàn) Win32 控制臺(tái) API,以及所有要求控制臺(tái)執(zhí)行的操作背后的邏輯。
          • Input Buffer: 保存由用戶輸入產(chǎn)生的鍵盤(pán)和鼠標(biāo)事件記錄
          • VT Parser: 如果啟動(dòng),則從文本中解析 VT 序列,根據(jù)找到的信息產(chǎn)生等效的 API 調(diào) I用
          • Output Buffer: 保存控制臺(tái)呈現(xiàn)的文本。本質(zhì)上是一個(gè)二維的 CHAR_INFO 結(jié)構(gòu)數(shù)組,其每個(gè)元素都包含了字符數(shù)據(jù)及其屬性(緩存區(qū)之下的更多信息)
          • Other: 未包含在上層呈現(xiàn),包含從注冊(cè)表或快捷文件中存儲(chǔ)/檢索基礎(chǔ)設(shè)置值。
          • ConHost Core - 控制臺(tái)的內(nèi)部控制和管道
          • Console UX App Services - 控制臺(tái)的 UX 和 UI 層

          Windows控制臺(tái)API

          從上述的控制臺(tái)架構(gòu)圖中可以看出,與NIX終端不同的是,控制臺(tái)發(fā)送/接收API調(diào)用和/或數(shù)據(jù)序列化為IO控制(IOCTL)消息,而不是序列化后的文本! 甚至從(主要是Linux)命令行應(yīng)用程序接收的文本中所嵌入的ANSI/VT序列也被提取、解析并轉(zhuǎn)換為API調(diào)用!

          這種差異揭示了*NIX和Windows之間關(guān)鍵的基本哲學(xué)差異:在*NIX中,“一切都是文件”,然而在Windows中,“一切都是對(duì)象”!

          兩種方法都有利有弊,我們將概括之,但避免在這里進(jìn)行長(zhǎng)篇大論。請(qǐng)記住,哲學(xué)中的這一關(guān)鍵差異是Windows和* NIX之間諸多差異的基礎(chǔ)!

          在 *NIX系統(tǒng)中,一切都是文件

          在60年代末和70年代初Unix被第一次實(shí)現(xiàn)的時(shí)候,其中一個(gè)核心原則就是任何東西都可以被抽象成文件流,一個(gè)關(guān)鍵目標(biāo)是簡(jiǎn)化對(duì)設(shè)備和外設(shè)的訪問(wèn)處理:如果所有的設(shè)備都在系統(tǒng)中以文件系統(tǒng)的形式存在,那么現(xiàn)存的代碼就可以不做修改地直接訪問(wèn)這些設(shè)備。

          這個(gè)原則影響深遠(yuǎn):你可以通過(guò)偽文件系統(tǒng)或虛擬文件系統(tǒng)來(lái)瀏覽和查詢大量的基于*NIX的系統(tǒng)和機(jī)器配置,它們僅僅是”表現(xiàn)得“像是“文件”或“文件夾”,實(shí)際可能是機(jī)器配置或硬件。

          例如,在Linux中,你可以通過(guò)訪問(wèn) /proc/cpuinfo 虛擬文件節(jié)點(diǎn)來(lái)查看CPU的一些信息:

          這個(gè)模型是如此簡(jiǎn)單和一致,但它也存在一些額外開(kāi)銷:從這些偽文件中提取或查詢特殊的文本信息并從執(zhí)行命令中返回,經(jīng)常需要一些工具的輔助,比如:sed,awk,perl,python等。這些工具經(jīng)常被用來(lái)寫(xiě)腳本和命令來(lái)解析文本內(nèi)容、查找特殊模式、區(qū)域和值。這些腳本可以變得非常復(fù)雜,難以維護(hù)和碎片化。如果文本的結(jié)構(gòu)、布局或格式發(fā)生變更,那么許多腳本也需要隨之更新。

          在Windows中,任何事物都是對(duì)象

          當(dāng)Windows NT被設(shè)計(jì)和構(gòu)建時(shí),“對(duì)象”被視為軟件設(shè)計(jì)的未來(lái):“面向?qū)ο蟆钡恼Z(yǔ)言比洞穴里的兔子更快出現(xiàn) - Simula和Smalltalk已經(jīng)建立起來(lái),而C ++正變得越來(lái)越流行。其他面向?qū)ο蟮恼Z(yǔ)言,如Python,Eiffel,Objective-C,ObjectPascal / Delphi,Java,C#等許多其他語(yǔ)言都在快速發(fā)展緊隨其后。

          不可避免的是,它成型于面向?qū)ο蟠蠛脮r(shí)期(大約1989年)中,Windows NT的設(shè)計(jì)理念是“一切都是對(duì)象”。事實(shí)上,NT內(nèi)核最重要的部分之一是“對(duì)象管理器”!

          Windows NT公開(kāi)了一組豐富的Win32 API,可以調(diào)用這些API來(lái)從操作系統(tǒng)獲取和/或操作對(duì)象。開(kāi)發(fā)人員使用Win32 API來(lái)收集和呈現(xiàn)* NIX偽文件和工具提供的類似信息,但是通過(guò)對(duì)象和結(jié)構(gòu)。并且因?yàn)榻馕銎鳎幾g器和分析器理解對(duì)象的結(jié)構(gòu),所以通常可以更早地捕獲許多編碼錯(cuò)誤,從而幫助驗(yàn)證程序員的意圖在語(yǔ)法和邏輯上是否正確。隨著時(shí)間的推移,這也可以減少系統(tǒng)破損,波動(dòng)和“攪動(dòng)”。

          所以,回到我們關(guān)于Windows控制臺(tái)的中心討論:NT團(tuán)隊(duì)決定構(gòu)建一個(gè)“控制臺(tái)”,它在幾個(gè)關(guān)鍵領(lǐng)域區(qū)別于傳統(tǒng)的* NIX終端:

          1. 控制臺(tái)API:Windows Console可以通過(guò)豐富的Console API進(jìn)行操作和控制,而不是依賴程序員生成“難以驗(yàn)證”的ANSI / VT序列的能力。
          2. 公共服務(wù):為避免每個(gè)命令行shell一次又一次地重新實(shí)現(xiàn)相同的服務(wù)(例如命令歷史記錄,命令別名),控制臺(tái)本身提供了一些這些服務(wù),可通過(guò)Console API訪問(wèn)

          Windows控制臺(tái)的問(wèn)題

          雖然Console的API已經(jīng)證明在Windows命令行工具和服務(wù)領(lǐng)域非常流行,但以API為中心的模型對(duì)命令行方案提出了一些挑戰(zhàn):

          只有Windows實(shí)現(xiàn)了Console API

          許多Windows命令行工具和應(yīng)用程序廣泛使用Console API。

          問(wèn)題呢?這些API僅適用于Windows。

          因此,結(jié)合其他差異化因素(例如過(guò)程生命周期差異等),Windows命令行應(yīng)用程序并不總是易于移植到* NIX,反之亦然。

          因此,Windows生態(tài)系統(tǒng)開(kāi)發(fā)了自己的,通常類似但通常不同的命令行工具和應(yīng)用程序。這意味著用戶在使用Windows時(shí)必須學(xué)習(xí)一組命令行應(yīng)用程序和工具,shell,腳本語(yǔ)言等,而在使用* NIX時(shí)則需要學(xué)習(xí)另一組。

          這個(gè)問(wèn)題沒(méi)有簡(jiǎn)單的快速解決方案:Windows控制臺(tái)和命令行不能簡(jiǎn)單地丟棄并被bash和iTerm2取代 - 有數(shù)以億計(jì)的應(yīng)用程序和腳本依賴于Windows控制臺(tái)和Cmd / PowerShell shells。

          像Cygwin這樣的第三方工具可以很好地將許多核心GNU工具和兼容性庫(kù)移植到Windows,但是它們無(wú)法運(yùn)行未移植的,未經(jīng)修改的Linux二進(jìn)制文件。這非常重要,因?yàn)樵S多Ruby,Python,Node包和模塊依賴于或包裝Linux二進(jìn)制文件,或者依賴于* NIX運(yùn)轉(zhuǎn)狀態(tài)。

          這些原因促使微軟通過(guò)在 Windows的子系統(tǒng)Linux(WSL)上本地運(yùn)行真正的,未經(jīng)修改的Linux二進(jìn)制文件和工具來(lái)擴(kuò)展Windows的兼容性。使用WSL的用戶現(xiàn)在可以在同一臺(tái)機(jī)器上并行下載和安裝一個(gè)或多個(gè)Linux發(fā)行版,并使用apt / zypper / npm / gem / etc.安裝和運(yùn)行絕大多數(shù)Linux命令行工具以及他們喜歡的Windows應(yīng)用程序和工具。

          但是,還有一些控制臺(tái)提供的東西尚未被非Microsoft終端采用:具體來(lái)說(shuō),Windows控制臺(tái)提供命令歷史記錄和命令別名服務(wù),從而無(wú)需每個(gè)命令行shell(特別是)重新實(shí)現(xiàn)相同的功能。

          把 Windows 命令行遠(yuǎn)程化是困難的

          正如我們?cè)?Command-Line Backgrounder 一文中所討論的那樣,終端最初與它們所連接的計(jì)算機(jī)是分開(kāi)的。快進(jìn)到今天,這種設(shè)計(jì)仍然存在:大多數(shù)現(xiàn)代終端和命令行應(yīng)用程序/shell 等等是由進(jìn)程或機(jī)器邊界分隔的。

          在基于 *NIX 的平臺(tái)上,終端和命令行應(yīng)用程序的分離并通過(guò)簡(jiǎn)單的字符進(jìn)行通信的概念導(dǎo)致 *NIX 命令行易于從遠(yuǎn)程計(jì)算機(jī)/設(shè)備訪問(wèn)和操作:只要終端和命令行應(yīng)用程序可以通過(guò)某種類型的有序串行通信基礎(chǔ)架構(gòu)(TTY/PTY 等)傳輸字符流,遠(yuǎn)程操作 *NIX 機(jī)器的命令行是非常簡(jiǎn)單的。

          但是在 Windows 上,許多命令行應(yīng)用程序依賴于調(diào)用 Console API,并假設(shè)它們與控制臺(tái)本身在同一臺(tái)機(jī)器上運(yùn)行。這使得遠(yuǎn)程操作 Windows 命令行 shell/工具等變得很困難:在遠(yuǎn)程計(jì)算機(jī)上運(yùn)行的命令行應(yīng)用程序如何調(diào)用在用戶本地計(jì)算機(jī)的控制臺(tái)上的 API 呢?更糟糕的是,如果遠(yuǎn)程命令行應(yīng)用程序通過(guò) Mac 或 Linux 機(jī)器上的終端訪問(wèn),它如何調(diào)用 Console API 呢?!

          很抱歉開(kāi)個(gè)玩笑,但我們將在以后的文章中更詳細(xì)地闡釋這個(gè)主題!

          啟動(dòng)控制臺(tái)或者不!

          通常,在基于 *NIX 的系統(tǒng)上,當(dāng)用戶想要啟動(dòng)一個(gè)命令行工具時(shí),他們首先會(huì)啟動(dòng)一個(gè)終端。然后終端啟動(dòng)一個(gè)默認(rèn)的 shell ,或者可以配置為啟動(dòng)一個(gè)特定的應(yīng)用程序/工具。終端和命令行應(yīng)用程序通過(guò)偽終端(PTY)交換字符流進(jìn)行通信,直到一個(gè)或兩個(gè)字符終止。

          然而,在 Windows 系統(tǒng)上,事情就不一樣了:Windows 用戶永遠(yuǎn)不會(huì)啟動(dòng)控制臺(tái)(conhost.exe)——然而他們會(huì)啟動(dòng)像是 Cmd.exe,PowerShell.exe,wsl.exe 等等這樣的命令行 shell 和應(yīng)用程序。Windows 系統(tǒng)將新啟動(dòng)的應(yīng)用程序連接到當(dāng)前控制臺(tái)(如果是從命令行啟動(dòng)的話),或者連接到新創(chuàng)建的控制臺(tái)實(shí)例。

          # 現(xiàn)在要說(shuō)的?

          是的,在 Windows 系統(tǒng)中,用戶啟動(dòng)命令行應(yīng)用程序,而不是控制臺(tái)本身。

          如果用戶從現(xiàn)有的命令行 shell 啟動(dòng)命令行應(yīng)用程序,Windows 通常會(huì)將新啟動(dòng)的 .exe(可執(zhí)行文件) 附加到當(dāng)前控制臺(tái)。否則,Windows 會(huì)將一個(gè)新的控制臺(tái)實(shí)例與新推出的應(yīng)用程序綁定在一起。

          小白說(shuō):很多人說(shuō)“命令行程序在控制臺(tái)運(yùn)行”。這不是真的,而且導(dǎo)致很多關(guān)于控制臺(tái)和命令行應(yīng)用程序如何工作的困惑!命令行應(yīng)用程序和它們的控制臺(tái)都在各自獨(dú)立的 Win32 進(jìn)程中運(yùn)行。請(qǐng)通過(guò)指出“命令行工具/應(yīng)用程序連接到控制臺(tái)運(yùn)行”(或類似的)來(lái)幫助糾正這種誤解。謝謝!

          聽(tīng)起來(lái)不錯(cuò),對(duì)吧?嗯…不;這里有一些問(wèn)題:

          1.控制臺(tái)和命令行應(yīng)用程序通過(guò)經(jīng)由驅(qū)動(dòng)程序的 IOCTL 消息進(jìn)行通信,而不是通過(guò)文本流進(jìn)行通信

          2.windows 要求 ConHost.exe 必須是連接到命令行應(yīng)用程序的控制臺(tái)程序

          3.Windows 控制了控制臺(tái)和命令行應(yīng)用程序通信之間通信“管道”的創(chuàng)建

          這些都是明顯的限制:如果你想為 Windows 創(chuàng)建一個(gè)替代控制臺(tái)的應(yīng)用程序,該怎么辦?你將如何發(fā)送鍵盤(pán)、鼠標(biāo)、筆等等外設(shè)的信息?如果你無(wú)法訪問(wèn)連接你新控制臺(tái)和命令行應(yīng)用程序的通信“管道”,用戶將怎么對(duì)命令行應(yīng)用程序進(jìn)行操作?

          遺憾的是,這些情況并不好:有一些很棒的用于 Windows 的第三方控制臺(tái)(和服務(wù)器應(yīng)用程序)(例如 ConEmu/Cmder, Console2/ConsoleZ, Hyper, Visual Studio Code, OpenSSH 等),他們必須通過(guò)離奇的跳轉(zhuǎn)才能像正常的控制臺(tái)一樣運(yùn)行!

          舉例來(lái)說(shuō),第三方控制臺(tái)必須在屏幕外啟動(dòng)一個(gè)命令行應(yīng)用程序,例如(-32000,-32000)。然后,他們必須向屏幕外控制臺(tái)發(fā)送擊鍵信息,然后收集屏幕外控制臺(tái)的文本內(nèi)容并在自己的 UI 上重新繪制它們!

          我知道,這很瘋狂,對(duì)吧? !這證明了這些應(yīng)用程序創(chuàng)造者們的獨(dú)創(chuàng)性和決心,這些程序甚至還在有效的運(yùn)行!

          這顯然是我們急于補(bǔ)救的一種情況。請(qǐng)繼續(xù)關(guān)注這部分內(nèi)容的更多信息——在這方面有一些好消息!

          Windows 控制臺(tái) & VT

          如上所述,Windows 控制臺(tái)提供了大量 API。使用控制臺(tái) API,命令行應(yīng)用程序和工具可寫(xiě)入文本,更改文本顏色,移動(dòng)光標(biāo)等。并且,由于控制臺(tái) API 的存在,Windows 控制臺(tái)幾乎不需要支持 ANSI/VT 序列,這些序列在其他平臺(tái)上提供非常類似的功能。

          實(shí)際上,在 Windows 10 之前,Windows 控制臺(tái)僅實(shí)現(xiàn)了對(duì) ANSI/VT 序列的最低限度支持:

          從2014年開(kāi)始,微軟組建了一個(gè)新的 Windows 控制臺(tái)團(tuán)隊(duì),使得這一切都發(fā)生了變化。控制臺(tái)團(tuán)隊(duì)的最高優(yōu)先級(jí)事項(xiàng)之一是實(shí)現(xiàn)對(duì) ANSI/VT 序列的全面支持,以便渲染在 Windows 子系統(tǒng)之Linux(WSL)和遠(yuǎn)程 *NIX 機(jī)器上運(yùn)行的 *NIX 應(yīng)用程序的輸出。您可以在本系列的上一篇文章中閱讀更多關(guān)于這個(gè)故事的內(nèi)容。

          控制臺(tái)團(tuán)隊(duì)迅速為 Windows 10 的控制臺(tái)添加了對(duì) ANSI/VT 序列的全面支持,使用戶能夠使用和享用大量 Windows 和 Linux 命令行工具和應(yīng)用程序。

          該團(tuán)隊(duì)繼續(xù)改進(jìn)和完善每個(gè)操作系統(tǒng)發(fā)布版本上的控制臺(tái)對(duì) VT 的支持,并對(duì)您在我們的 GitHub 問(wèn)題跟蹤器上提交的任何問(wèn)題表示感謝。

          處理Unicode

          一個(gè)快速的Unicode回顧:

          Unicode或ISO/IEC 10646是一個(gè)國(guó)際標(biāo)準(zhǔn),定義了地球上幾乎每個(gè)書(shū)寫(xiě)系統(tǒng)中所使用的每個(gè)字符/字形,以及當(dāng)今使用的許多非腳本符號(hào)和字符大小的圖像(例如表情符號(hào))。目前(2018年7月),Unicode 11定義了137439個(gè)字符,包含146個(gè)現(xiàn)代和歷史文字系統(tǒng)!

          Unicode還定義了幾種字符編碼,包括UTF-8, UTF-16, 和UTF-32:

          • UTF-8: 前127個(gè)編碼點(diǎn)使用1字節(jié)(主要為了維持與ASCII的兼容性),其他字符可選附加長(zhǎng)度1-4字節(jié)
          • UTF-16/UCS-2: 每個(gè)字符兩個(gè)字節(jié)。UCS-2 (被Windows內(nèi)部使用)z支持對(duì)前65536編碼點(diǎn)(統(tǒng)稱為基本多語(yǔ)言平面-BMP)。UTF-16通過(guò)17個(gè)額外的字符平面擴(kuò)展了UCS-2。
          • UTF-32: 每個(gè)字符4字節(jié)

          由于UTF-8的高效的存儲(chǔ)要求以及在HTML頁(yè)面中的廣泛使用,它是目前最流行的編碼。

          UTF-16/UCS-2都是常見(jiàn)的,盡管在已存儲(chǔ)文檔(例如網(wǎng)頁(yè)、代碼等)中其使用比例正在降低。UTF-32是很少使用的,因?yàn)樗男实颓掖鎯?chǔ)需要相當(dāng)大的空間。

          很好,所以我們有有效并且高效的方式來(lái)表示和存儲(chǔ)Unicode字符了!

          所以?

          哎呀,Windows控制臺(tái)及其API是在創(chuàng)建Unicode之前創(chuàng)建的!

          Windows控制臺(tái)將文本(隨后在屏幕上繪制)存儲(chǔ)為每個(gè)單元需要2個(gè)字節(jié)的UCS-2字符。

          命令行應(yīng)用程序使用控制臺(tái)API將文本寫(xiě)入到控制臺(tái)中。處理文本的控制臺(tái)API有兩種形式 - 帶有A后綴處理的單字節(jié)/字符串的函數(shù),帶有W后綴處理雙字節(jié)(wchar)/字符串的函數(shù):

          例如,WriteConsoleOutputCharacter()函數(shù)編譯為ASCII項(xiàng)目的WriteConsoleOutputCharacterA(),或Unicode項(xiàng)目的WriteConsoleOutputCharacterW()。如果需要指定處理方式,代碼中可以直接調(diào)用... A或...W后綴的函數(shù)。

          注意:每個(gè)W API至少支持UCS-2,因?yàn)檫@是在進(jìn)行A/W拆分時(shí)就存在的事情,我們認(rèn)為這樣做會(huì)很棒。但許多W API已更新為在同一渠道上也支持UTF-16

          。并非所有W API都可以支持UTF-16,但所有W API至少可以支持UCS-2。

          此外,控制臺(tái)不支持一些較新的Unicode功能,包括零寬度連接符(ZWJ),該符號(hào)被用于連接阿拉伯語(yǔ)和印度語(yǔ)中的其他單獨(dú)字符,并將表情符號(hào)字符組合成一個(gè)可視字形!

          那么如果你想在控制臺(tái)上輸出一個(gè)ninjacat表情符號(hào)或復(fù)雜的多字節(jié)中文/阿拉伯字符會(huì)怎樣呢? 糟糕的是,你做不到

          Console API不僅不支持長(zhǎng)度超過(guò)2字節(jié)/字形的Unicode字符(NinjaCat表情符號(hào)需要8個(gè)字節(jié)!),但Console內(nèi)部的UCS-2緩沖區(qū)不能存儲(chǔ)該數(shù)據(jù)的額外字節(jié),更糟糕的是 ,Console當(dāng)前的基于GDI的渲染器甚至無(wú)法繪制字形,即使緩沖區(qū)可以存儲(chǔ)它!

          可嘆! 這就是遺留代碼的樂(lè)趣。

          但是,我也會(huì)希望你們到此打住 - 我們將在本系列的新一篇文章中回到這個(gè)主題。 敬請(qǐng)關(guān)注!

          所以,我們?cè)谀睦?

          再一次,親愛(ài)的讀者,如果你讀過(guò)以上的所有內(nèi)容,謝謝你,也祝賀你 —— 你現(xiàn)在比你的大多數(shù)朋友都更了解 Windows 控制臺(tái),甚至可能比你想知道的還要多!祝你幸運(yùn)!

          在這篇文章中,我們涵蓋了很多內(nèi)容:

          Windows控制臺(tái)的主要構(gòu)建模塊:

          • API Server —— 通過(guò) IOCTL 消息向驅(qū)動(dòng)程序發(fā)送或從驅(qū)動(dòng)程序接收序列化的 API 調(diào)用和文本數(shù)據(jù)。
          • API——控制臺(tái)的功能函數(shù)。
          • Buffers —— 輸入緩沖用于存儲(chǔ)用戶輸入,輸出緩沖用于存儲(chǔ)輸出和顯示文本。
          • 輸入緩沖存儲(chǔ)用戶輸入,輸出緩沖存儲(chǔ)輸出和顯示文本。
          • VT Parser —— 將嵌入文本流的 ANSI/VT 序列轉(zhuǎn)換為 API 調(diào)用
          • Console UX —— 控制臺(tái)的用戶界面狀態(tài)、設(shè)置和功能
          • Other —— Misc 生命周期、安全性等。
          • Condrv.sys —— 控制臺(tái)通信驅(qū)動(dòng)程序
          • ConHost.exe —— 控制臺(tái)用戶體驗(yàn)、內(nèi)部構(gòu)件和管道:

          控制臺(tái)做什么?

          • 向連接的命令行應(yīng)用程序發(fā)送用戶輸入
          • 接收并顯示連接的命令行應(yīng)用程序輸出

          控制臺(tái)與 *NIX 終端有什么不同

          • *NIX:“一切都是文件/文本流”
          • Windows:“一切都是對(duì)象,可以通過(guò) API 進(jìn)行訪問(wèn)”

          控制臺(tái)存在的問(wèn)題

          • 大部分都在 Windows 10 中得到了修復(fù)
          • 只有 ConHost.exe 可以附加到命令行應(yīng)用程序
          • 第三方終端被迫創(chuàng)建屏幕外控制臺(tái),并向它發(fā)送按鍵和屏幕信息,或從中接收按鍵和屏幕信息
          • 遠(yuǎn)程操作 Windows 命令行應(yīng)用程序和工具存在困難
          • 來(lái)自 Windows 的端口命令行 APP 的工作變得更多
          • 控制臺(tái)和命令行應(yīng)用程序通過(guò)序列化 API 調(diào)用請(qǐng)求和文本組成的 IOCTL 消息進(jìn)行通信
          • 只有 Windows 命令行應(yīng)用程序能調(diào)用控制臺(tái) API
          • 應(yīng)用程序調(diào)用 Windows API 與控制臺(tái)交互
          • 對(duì) IOCTL 的依賴打破了“字符交換”原則的終端設(shè)計(jì)
          • 使從非 Windows 機(jī)器操作遠(yuǎn)程 Windows 命令行工具變得困難
          • 啟動(dòng) Windows 命令行應(yīng)用程序是“不常用的”
          • Windows一直不識(shí)別ANSI/VT序列
          • 控制臺(tái)對(duì) Unicode 的支持有限,目前正在努力處理存儲(chǔ)和展現(xiàn)現(xiàn)代 UTF-8 和需要零寬度連接符的字符

          在本系列的后續(xù)文章中,我們將深入探討控制臺(tái),并討論如何處理這些問(wèn)題……和更多其他內(nèi)容!

          像往常一樣,請(qǐng)繼續(xù)關(guān)注我們。

          本文由oschina作者參與翻譯,如有侵權(quán),請(qǐng)聯(lián)系刪除。

          著網(wǎng)絡(luò)技術(shù)的發(fā)展,越來(lái)越多的應(yīng)用基于互聯(lián)網(wǎng)發(fā)布,再好的應(yīng)用,如果打開(kāi)速度慢,10個(gè)用戶會(huì)有9個(gè)用戶選擇離開(kāi),相關(guān)統(tǒng)計(jì)數(shù)據(jù)顯示,每增加0.1秒的加載延遲,將會(huì)導(dǎo)致客戶活躍度下降1%。在目前獲客成本較高,用戶面臨眾多可選項(xiàng)的情況下,如何提高用戶訪問(wèn)的體驗(yàn),給用戶留下良好的第一印象,提高ROI,是所有開(kāi)發(fā)互聯(lián)網(wǎng)應(yīng)用的企業(yè)都關(guān)注的核心問(wèn)題。

          影響應(yīng)用資源加載的因素很多,服務(wù)器性能、網(wǎng)絡(luò)傳輸質(zhì)量、網(wǎng)站出口帶寬狀況、DNS解析時(shí)間、網(wǎng)頁(yè)內(nèi)容大小、終端用戶網(wǎng)絡(luò)質(zhì)量等,在云計(jì)算技術(shù)高度發(fā)達(dá)的今天,并非每一個(gè)環(huán)節(jié)的優(yōu)化都需要企業(yè)自己造輪子,更為便捷可行的選擇是:借助云服務(wù)商提供的相應(yīng)加速服務(wù)來(lái)優(yōu)化企業(yè)的應(yīng)用,可以實(shí)現(xiàn)更低的成本、更敏捷快速的建設(shè)、更強(qiáng)壯和高性能的服務(wù),用來(lái)取代傳統(tǒng)的用昂貴的成本購(gòu)買大量服務(wù)器、帶寬做自建的模式。

          標(biāo)準(zhǔn)CDN服務(wù)所擅長(zhǎng)加速的內(nèi)容是靜態(tài)內(nèi)容,如文件、圖片、視頻等,通過(guò)CDN的緩存策略來(lái)緩存并實(shí)現(xiàn)加速。但互聯(lián)網(wǎng)上的應(yīng)用復(fù)雜,源站往往也會(huì)有很多經(jīng)常變化的內(nèi)容---動(dòng)態(tài)內(nèi)容,如用戶登錄、內(nèi)容搜索、視頻彈幕、直播評(píng)論、購(gòu)物交易、股票行情、體育實(shí)況等,很多時(shí)候這些應(yīng)用沒(méi)有做動(dòng)靜分離設(shè)計(jì)和動(dòng)靜內(nèi)容分別處理,這也造成很多應(yīng)用即使采用了標(biāo)準(zhǔn)CDN服務(wù),卻沒(méi)有達(dá)到很好的加速效果,因?yàn)閯?dòng)態(tài)部分內(nèi)容的加速性能并沒(méi)有得到很好的優(yōu)化。

          對(duì)應(yīng)上敘的情況,我們推薦使用阿里云全站加速產(chǎn)品,阿里云全站加速產(chǎn)品是阿里云自主研發(fā)的融合了動(dòng)態(tài)加速技術(shù)和靜態(tài)加速技術(shù)的CDN產(chǎn)品,可以很好的解決頁(yè)面動(dòng)靜態(tài)資源混合、跨運(yùn)營(yíng)商、網(wǎng)絡(luò)不穩(wěn)定、單線源站、突發(fā)流量、網(wǎng)絡(luò)擁塞等諸多因素導(dǎo)致的響應(yīng)慢、丟包、服務(wù)不穩(wěn)定的問(wèn)題,全面提升全站性能和用戶體驗(yàn)

          阿里云全站加速產(chǎn)品可以有效提升靜態(tài)、動(dòng)態(tài)內(nèi)容的加速效果。下面的圖我們可以具體看下,使用全站加速產(chǎn)品前后的效果對(duì)比。從實(shí)際的測(cè)試結(jié)果圖中可以看到使用全站加速前,無(wú)論訪問(wèn)效率,還是節(jié)點(diǎn)加速效果,都較未使用前有了明顯的提升。

          那阿里云全站加速怎么樣才能夠?qū)崿F(xiàn)以上的效果呢?主要通過(guò)以下四個(gè)方面完成:

          第一、全球覆蓋的加速節(jié)點(diǎn)阿里云在全球有2800+節(jié)點(diǎn),這些節(jié)點(diǎn)涵蓋了中國(guó)國(guó)內(nèi)、歐洲、美洲、亞洲、非洲等全世界的大部分區(qū)域,同時(shí)這些節(jié)點(diǎn)都是互聯(lián)了當(dāng)?shù)刈詈诵牡倪\(yùn)營(yíng)商網(wǎng)絡(luò),阿里云全站加速可以保證全球用戶都能夠找到離他最近的、訪問(wèn)質(zhì)量最好的和用戶接入網(wǎng)絡(luò)運(yùn)營(yíng)商相對(duì)應(yīng)的加速節(jié)點(diǎn)。

          第二、全球智能調(diào)度系統(tǒng)在上面我們講到了覆蓋,只有覆蓋還是不夠的,還需要把用戶調(diào)度到對(duì)應(yīng)的最合理的節(jié)點(diǎn),這個(gè)環(huán)節(jié)就非常取決于調(diào)度的IP庫(kù)的完善性和準(zhǔn)確性。阿里云全球智能調(diào)度系統(tǒng)結(jié)合阿里整體龐大的用戶基礎(chǔ)(淘寶、天貓、優(yōu)酷等),基于這些用戶基礎(chǔ)可以打造非常詳盡、精準(zhǔn)的用戶IP庫(kù),可以有效保證用戶接入匹配的高準(zhǔn)確度。

          第三、智能自適應(yīng)緩存業(yè)界一般對(duì)于全站加速的場(chǎng)景,需要客戶手動(dòng)配置動(dòng)靜態(tài)內(nèi)容,來(lái)讓CDN平臺(tái)執(zhí)行動(dòng)態(tài)和靜態(tài)兩種加速模式。但是很多網(wǎng)站特別是中小客戶,動(dòng)靜態(tài)內(nèi)容區(qū)分不是很清晰,不便于做動(dòng)靜態(tài)的區(qū)分。全站加速推出的動(dòng)靜態(tài)智能自適應(yīng)功能,可以讓客戶不再需要繁瑣配置動(dòng)靜態(tài)內(nèi)容區(qū)分,全站加速會(huì)自動(dòng)的分析和識(shí)別請(qǐng)求和響應(yīng)特征,智能的對(duì)訪問(wèn)的內(nèi)容進(jìn)行動(dòng)靜態(tài)分類,讓可以緩存的靜態(tài)內(nèi)容避免了動(dòng)態(tài)化訪問(wèn)源站,從而降低了回源帶寬、回源時(shí)間而提升了性能。當(dāng)然,阿里云全站加速平臺(tái)也支持客戶通過(guò)自定義的方案,很方便的自行定義實(shí)動(dòng)靜態(tài)內(nèi)容加速規(guī)則。

          此外,針對(duì)靜態(tài)內(nèi)容,阿里云全站加速還可以通過(guò)智能壓縮功,自動(dòng)對(duì)靜態(tài)文件進(jìn)行Gzip壓縮,以及通過(guò)頁(yè)面優(yōu)化,對(duì)當(dāng)前域名下所有HTML頁(yè)面中冗余的注釋和重復(fù)的空白符進(jìn)行優(yōu)化,以減小傳輸文件大小,減少流量支出和提升加速分發(fā)效率。

          第四、智能路由對(duì)于無(wú)法緩存或者不允許緩存的內(nèi)容,最核心的處理邏輯是實(shí)現(xiàn)路徑加速,阿里云的路徑加速是通過(guò)智能路由來(lái)實(shí)現(xiàn)的,在廣泛覆蓋的節(jié)點(diǎn)之間,通過(guò)實(shí)時(shí)探測(cè)通信網(wǎng)絡(luò)質(zhì)量,并根據(jù)探測(cè)的質(zhì)量,進(jìn)行路徑的有效分析,同時(shí)結(jié)合阿里達(dá)摩院的最佳數(shù)據(jù)計(jì)算模型,提供一條從用戶的接入點(diǎn)到源站之間一個(gè)最優(yōu)的路徑,實(shí)現(xiàn)最好的加速效果。

          阿里云全站加速產(chǎn)品除了通過(guò)以上的策略提供了優(yōu)秀的加速效果之外,還提供了下面的相關(guān)的功能模塊讓客戶的服務(wù)可以變得更靈活和更健壯,以及還提供了更廣泛和新穎的加速模式:

          第一、源站策略1、智能回源策略全站加速除了提供最優(yōu)鏈路回源來(lái)保證最好的服務(wù)質(zhì)量的同時(shí),還提供了豐富的回源策略管理。很多客戶的場(chǎng)景處于安全和自身業(yè)務(wù)的需求,往往會(huì)有一些復(fù)雜的策略需要CDN來(lái)適配。目前全站加速在回源策略方面具有豐富的功能。

          1. 可以根據(jù)特定的URL回不同的源站;
          2. 可以根據(jù)區(qū)分國(guó)內(nèi)和海外客戶,進(jìn)行分國(guó)內(nèi)和海外回源;
          3. 可以根據(jù)網(wǎng)民的DNS情況,回對(duì)應(yīng)區(qū)域的源站;

          2、靈活回源配置和重試容災(zāi)策略阿里云全站加速提供了靈活的回源配置策略,可以根據(jù)需求配置多主源(可設(shè)置不同的回源權(quán)重)、主備源,源站可以使用IP和域名。

          網(wǎng)絡(luò)情況瞬息萬(wàn)變,連接抖動(dòng)和擁堵時(shí)常發(fā)生,在長(zhǎng)鏈路傳輸時(shí),情況會(huì)更加嚴(yán)峻。通常情況下在回源階段,因?yàn)殒溌返募娱L(zhǎng),整體的網(wǎng)絡(luò)可控性降低。經(jīng)常會(huì)遇到回源節(jié)點(diǎn)的機(jī)房網(wǎng)絡(luò)有問(wèn)題,回源的某條運(yùn)營(yíng)商鏈路斷了等等相關(guān)的問(wèn)題。

          結(jié)合阿里云全站加速的提供了多種回源配置以及回源重試容災(zāi)策略,可以避免單源站問(wèn)題、源站單IP問(wèn)題、源站偶發(fā)不通等問(wèn)題,給業(yè)務(wù)提供更健壯的一個(gè)支撐。

          3、 WaitingRoom回源方案在回源的時(shí)候,有的時(shí)候會(huì)面臨一種場(chǎng)景,就是某次突發(fā)活動(dòng)請(qǐng)求的壓力非常大,舉個(gè)例子,比如在春運(yùn)火車票購(gòu)票的時(shí)候,請(qǐng)求的壓力可能是平時(shí)壓力的上百倍,短時(shí)間之內(nèi)沒(méi)有辦法擴(kuò)容這么大倍數(shù)能力的源站來(lái)解決請(qǐng)求問(wèn)題的(短時(shí)間內(nèi)擴(kuò)容源站上百倍的能力,會(huì)面臨到很大的成本壓力以及很長(zhǎng)的時(shí)間周期問(wèn)題)。針對(duì)上面這種場(chǎng)景,全站加速提供了WaitingRoom解決方案,可以靈活根據(jù)請(qǐng)求的URL、配置的回源比例、排隊(duì)時(shí)長(zhǎng),實(shí)現(xiàn)突發(fā)情況下有序的回源,保證源站服務(wù)穩(wěn)定性。

          第二、全鏈路https加速我們知道HTTP協(xié)議以明文方式發(fā)送內(nèi)容,不提供任何方式的數(shù)據(jù)加密。HTTPS協(xié)議是以安全為目標(biāo)的HTTP通道, HTTPS提供了身份驗(yàn)證與加密通訊方法,被廣泛用于網(wǎng)上安全敏感的通訊,例如交易支付、金融應(yīng)用、API接口、政務(wù)信息等。

          通過(guò)阿里云全站加速的控制臺(tái),可快速開(kāi)啟HTTPS協(xié)議,實(shí)現(xiàn)客戶端和全站加速之間請(qǐng)求的HTTPS加密,保障數(shù)據(jù)傳輸?shù)陌踩裕乐笻TTP明文傳輸中的被竊聽(tīng)、篡改、冒充和劫持風(fēng)險(xiǎn)。

          目前主流瀏覽器已將HTTP協(xié)議標(biāo)識(shí)為不安全,若堅(jiān)持使用HTTP協(xié)議,除了安全會(huì)埋下隱患外,終端客戶在訪問(wèn)網(wǎng)站時(shí)出現(xiàn)的不安全標(biāo)識(shí),也將影響訪問(wèn)。

          第三、WebSocket加速WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信,允許服務(wù)器主動(dòng)發(fā)送信息給客戶端。在WebSocket中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間創(chuàng)建持久性的連接,進(jìn)行雙向數(shù)據(jù)傳輸,客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單高效。

          阿里云的全站加速產(chǎn)品也提供了對(duì)應(yīng)的Websocket加速模式,通過(guò)阿里云全站加速的Websocket, 可在視頻彈幕、在線教育筆記大綱等信息推送、股票、金融產(chǎn)品實(shí)時(shí)報(bào)價(jià)、體育實(shí)況更新、視頻會(huì)議和聊天、基于位置的應(yīng)用等場(chǎng)景中使用,能偶更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)高效地進(jìn)行通訊。

          第四、IP應(yīng)用加速IP應(yīng)用加速旨在提供非標(biāo)準(zhǔn)HTTP協(xié)議用戶,特別是四層私有協(xié)議服務(wù)場(chǎng)景下,如金融類、游戲類、語(yǔ)音交互類等客戶提供網(wǎng)絡(luò)傳輸加速,降低服務(wù)的延遲和提升訪問(wèn)的可用性。

          阿里云IP應(yīng)用加速可以提供:私有協(xié)議做傳輸控制、智能選路優(yōu)化網(wǎng)絡(luò)層、源站透?jìng)鳌I(yè)務(wù)透明轉(zhuǎn)發(fā)無(wú)任何侵入,可以通過(guò)IP應(yīng)用加速靈活的使用TCP、UDP等相關(guān)協(xié)議做業(yè)務(wù)的傳輸。

          通過(guò)以上的了解,我們可以看到通過(guò)阿里云全站加速產(chǎn)品,可以有效的提升網(wǎng)站(APP)加速性能和用戶體驗(yàn)。在更多的業(yè)務(wù)搬到線上的時(shí)代,全站加速為游戲、在線教育、互聯(lián)網(wǎng)媒體、金融、商等行業(yè)中的數(shù)字化應(yīng)用提供了更優(yōu)的加速方案。如果您的業(yè)務(wù)中有全站加速的需求,可以通過(guò)阿里云官網(wǎng)、工單、服務(wù)群等方式進(jìn)行了解和反饋。

          比Python,JavaScript才是更適合寫(xiě)爬蟲(chóng)的語(yǔ)言。原因有如下三個(gè)方面:

          • JavaScript異步IO機(jī)制適用于爬蟲(chóng)這種IO密集型任務(wù)。JavaScript中的回調(diào)非常自然,使用異步網(wǎng)絡(luò)請(qǐng)求能夠充分利用CPU。
          • JavaScript中的jQuery毫無(wú)疑問(wèn)是最強(qiáng)悍的HTML解析工具,使用JavaScript寫(xiě)爬蟲(chóng)能夠減少學(xué)習(xí)負(fù)擔(dān)和記憶負(fù)擔(dān)。雖然Python中有PyQuery,但終究還是比不上jQuery自然。
          • 爬取結(jié)果多為JSON,JavaScript是最適合處理JSON的語(yǔ)言。

          一、任務(wù):爬取用戶在Github上的repo信息

          通過(guò)實(shí)例的方式學(xué)習(xí)爬蟲(chóng)是最好的方法,先定一個(gè)小目標(biāo):爬取github repo信息。入口URL如下,我們只需要一直點(diǎn)擊next按鈕就能夠遍歷到用戶的所有repo。

          https://github.com/{{username}}?tab=repositories

          獲取repo之后,可以做什么?

          • 統(tǒng)計(jì)用戶最常使用的語(yǔ)言,統(tǒng)計(jì)用戶語(yǔ)言使用分布情況統(tǒng)計(jì)用戶所獲取的star數(shù),fork數(shù)

          二、爬蟲(chóng)雙股劍:axios和jQuery

          axios是JavaScript中很常用的異步網(wǎng)絡(luò)請(qǐng)求庫(kù),相比jQuery,它更輕量、更專業(yè)。既能夠用于瀏覽器端,也可以用于Node。它的語(yǔ)法風(fēng)格是promise形式的。在本任務(wù)中,只需要了解如下用法就足夠了:

          axios.get(url).then((resp) => {
           請(qǐng)求成功,處理resp.data中的html數(shù)據(jù)
          }).catch((err) => {
           請(qǐng)求失敗,錯(cuò)誤處理
          })
          

          請(qǐng)求之后需要處理回復(fù)結(jié)果,處理回復(fù)結(jié)果的庫(kù)當(dāng)然是用jQuery。實(shí)際上,我們有更好的選擇:cheerio。

          在node下,使用jQuery,需要使用jsdom庫(kù)模擬一個(gè)window對(duì)象,這種方法效率較低,四個(gè)字形容就是:笨重穩(wěn)妥。

          如下代碼使用jQuery解析haha.html文件

          fs = require("fs")
          jquery=require('jquery')
          jsdom=require('jsdom') //fs.readFileSync()返回結(jié)果是一個(gè)buffer,相當(dāng)于byte[] 
          html = fs.readFileSync('haha.html').toString('utf8') 
          dom= new jsdom.JSDOM(html) 
          $=jquery(dom.window) console.log($('h1'))
          

          cheerio只實(shí)現(xiàn)了jQuery中的DOM部分,相當(dāng)于jQuery的一個(gè)子集。cheerio的語(yǔ)法和jQuery完全一致,在使用cheerio時(shí),幾乎感覺(jué)不到它和jQuery的差異。在解析HTML方面,毫無(wú)疑問(wèn),cheerio是更好的選擇。如下代碼使用cheerio解析haha.html文件。

          cheerio=require('cheerio')
          html=require('fs').readFileSync("haha.html").toString('utf8')
          $=cheerio.load(html)
          console.log($('h1'))
          

          只需20余行,便可實(shí)現(xiàn)簡(jiǎn)單的github爬蟲(chóng),此爬蟲(chóng)只爬取了一頁(yè)repo列表。

          var axios = require("axios")
          var cheerio = require("cheerio")
          axios.get("https://github.com/weiyinfu?tab=repositories").then(resp => {
           var $ = cheerio.load(resp.data)
           var lis = $("#user-repositories-list li")
           var repos = []
           for (var i = 0; i < lis.length; i++) {
           var li = lis.eq(i)
           var repo = {
           repoName: li.find("h3").text().trim(),
           repoUrl: li.find("h3 a").attr("href").trim(),
           repoDesc: li.find("p").text().trim(),
           language: li.find("[itemprop=programmingLanguage]").text().trim(),
           star: li.find(".muted-link.mr-3").eq(0).text().trim(),
           fork: li.find(".muted-link.mr-3").eq(1).text().trim(),
           forkedFrom: li.find(".f6.text-gray.mb-1 a").text().trim()
           }
           repos.push(repo)
           }
           console.log(repos)
          })
          

          三、更豐富的功能

          爬蟲(chóng)不是目的,而是達(dá)成目的的一種手段。獲取數(shù)據(jù)也不是目的,從數(shù)據(jù)中提取統(tǒng)計(jì)信息并呈現(xiàn)給人才是最終目的。

          在github爬蟲(chóng)的基礎(chǔ)上,我們可以擴(kuò)展出更加豐富的功能:使用echarts等圖表展示結(jié)果。

          要想讓更多人使用此爬蟲(chóng)工具獲取自己的github統(tǒng)計(jì)信息,就需要將做成一個(gè)網(wǎng)站的形式,通過(guò)搜索頁(yè)面輸入用戶名,啟動(dòng)爬蟲(chóng)立即爬取github信息,然后使用echarts進(jìn)行統(tǒng)計(jì)展示。網(wǎng)站肯定也要用js作為后端,這樣才能和js爬蟲(chóng)無(wú)縫銜接,不然還要考慮跨語(yǔ)言調(diào)用。js后端有兩大web框架express和koa,二者API非常相似,并無(wú)優(yōu)劣之分,但express更加流行。

          如上設(shè)計(jì)有一處用戶體驗(yàn)不佳的地方:當(dāng)啟動(dòng)爬蟲(chóng)爬取github信息時(shí),用戶可能需要等待好幾秒,這個(gè)過(guò)程不能讓用戶干等著。一種解決思路是:讓用戶看到爬蟲(chóng)爬取的進(jìn)度或者爬取過(guò)程。可以通過(guò)websocket向用戶推送爬取過(guò)程信息并在前端進(jìn)行展示。展示時(shí),使用類似控制臺(tái)的界面進(jìn)行展示。

          如何存儲(chǔ)爬取到的數(shù)據(jù)呢?使用MongoDB或者文件都可以,最好實(shí)現(xiàn)兩種存儲(chǔ)方式,讓系統(tǒng)的存儲(chǔ)方式變得可配置。使用MongoDB時(shí),用到j(luò)s中的連接池框架generic-pool。

          整個(gè)項(xiàng)目用到的庫(kù)包括:

          • express:后端框架
          • cheerio+axios:爬蟲(chóng)
          • ws:websocket展示爬取過(guò)程
          • webpack:打包工具
          • less:樣式語(yǔ)言
          • echarts:圖表展示
          • vue:模板渲染
          • jquery:DOM操作
          • mongodb:存儲(chǔ)數(shù)據(jù)
          • generic-pool:數(shù)據(jù)庫(kù)連接池

          試用地址:

          https://weiyinfu.cn/githubstatistic/search.html?

          案例地址:https://github.com/weiyinfu/GithubStatistic

          原文鏈接:https://zhuanlan.zhihu.com/p/53763115


          主站蜘蛛池模板: 乱中年女人伦av一区二区| 国产精品视频一区二区三区四| 亲子乱av一区二区三区| 无码乱人伦一区二区亚洲| 日本一区视频在线播放| 亚洲国产精品综合一区在线 | 精品国产日韩亚洲一区91| 国产一区二区视频在线播放| 国产综合视频在线观看一区| 乱精品一区字幕二区| 亚洲高清偷拍一区二区三区| 狠狠综合久久av一区二区| 无码一区二区波多野结衣播放搜索 | 亚洲国产精品一区二区三区在线观看 | 91在线精品亚洲一区二区| 国产日韩一区二区三区在线观看 | 夜夜添无码试看一区二区三区| 四虎一区二区成人免费影院网址| 国产日产久久高清欧美一区| 伊人久久精品无码麻豆一区 | 国产一区二区三区播放| 免费精品一区二区三区在线观看 | 无码视频一区二区三区在线观看| 亚洲国模精品一区| 久久精品国产一区二区三区| 亚州国产AV一区二区三区伊在| 日韩十八禁一区二区久久| 乱人伦一区二区三区| 制服中文字幕一区二区 | 国模视频一区二区| 精品国产免费一区二区| 国产伦精品一区二区三区免费迷| 美女免费视频一区二区| 国产激情一区二区三区在线观看| 一区视频免费观看| 鲁丝片一区二区三区免费| 色欲AV蜜臀一区二区三区| 亚洲一区二区三区免费观看| 欲色aV无码一区二区人妻| 制服美女视频一区| 亚洲国产精品第一区二区三区|