首先祝大家中秋節和國慶節快樂,歡迎大家來到「Python從零到壹」,在這裡我將分享約200篇Python系列文章,帶大家一起去學習和玩耍,看看Python這個有趣的世界。所有文章都將結合案例、代碼和作者的經驗講解,真心想把自己近十年的編程經驗分享給大家,希望對您有所幫助,文章中不足之處也請海涵。
Python系列整體框架包括基礎語法10篇、網絡爬蟲30篇、可視化分析10篇、機器學習20篇、大數據分析20篇、圖像識別30篇、人工智慧40篇、Python安全20篇、其他技巧10篇。您的關注、點讚和轉發就是對秀璋最大的支持,知識無價人有情,希望我們都能在人生路上開心快樂、共同成長。
本文參考了作者CSDN的文章,連結如下:
同時,作者新開的「娜璋AI安全之家」將專注於Python和安全技術,主要分享Web滲透、系統安全、人工智慧、大數據分析、圖像識別、惡意代碼檢測、CVE復現、威脅情報分析等文章。雖然作者是一名技術小白,但會保證每一篇文章都會很用心地撰寫,希望這些基礎性文章對你有所幫助,在Python和安全路上與大家一起進步。
目錄:
一.什麼是網絡爬蟲
二.正則表達式
三.Python網絡數據爬取常用模塊
1.urllib模塊
2.urlparse模塊
四.正則表達式抓取網絡數據的常見方法
1.抓取標籤間的內容
2.爬取標籤中的參數
3.字符串處理及替換
五.個人博客爬取實例
一.什麼是網絡爬蟲隨著網際網路的迅速發展,全球資訊網成為大量信息的載體,越來越多的網民可以通過網際網路獲取所需的信息,同時如何有效地提取並利用這些信息也成為了一個巨大的挑戰。搜尋引擎(Search Engine)作為輔助人們檢索信息的工具,它成為了用戶訪問全球資訊網的入口和工具,常見的搜尋引擎比如Google、Yahoo、百度、搜狗等。但是,這些通用性搜尋引擎也存在著一定的局限性,比如搜尋引擎返回的結果包含大量用戶不關心的網頁;再如它們是基於關鍵字檢索,缺乏語義理解,導致反饋的信息不準確;通用的搜尋引擎無法處理非結構性數據,圖片、音頻、視頻等複雜類型的數據。
為了解決上述問題,定向抓取相關網頁資源的網絡爬蟲應運而生,下圖是Google搜尋引擎的架構圖,它從全球資訊網中爬取相關數據,通過文本和連接分析,再進行打分排序,最後返回相關的搜索結果至瀏覽器。同時,現在比較熱門的知識圖譜也是為了解決類似的問題而提出的。
網絡爬蟲又被稱為網頁蜘蛛或網絡機器人,它是一種按照一定的規則,自動地抓取全球資訊網信息的程序或者腳本。網絡爬蟲根據既定的抓取目標,有選擇的訪問全球資訊網上的網頁與相關的連結,獲取所需要的信息。與通用爬蟲不同,定向爬蟲並不追求大的覆蓋,而將目標定為抓取與某一特定主題內容相關的網頁,為面向主題的用戶查詢準備數據資源。
網絡爬蟲按照系統結構和實現技術,大致可以分為以下幾種類型:通用網絡爬蟲(General Purpose Web Crawler)、聚焦網絡爬蟲(Focused Web Crawler)、增量式網絡爬蟲(Incremental Web Crawler)、深層網絡爬蟲(Deep Web Crawler)。實際的網絡爬蟲系統通常是幾種爬蟲技術相結合實現的。
數據分析通常包括前期準備、數據爬取、數據預處理、數據分析、可視化繪圖及分析評估六個步驟,如下圖所示。其中數據爬取主要劃分為四個步驟:
需求分析。首先需要分析網絡數據爬取的需求,了解所爬取主題的網址、內容分布,所獲取語料的欄位、圖集等內容。
技術選擇。網頁抓取技術可以通過Python、Java、C++、C#等不同程式語言實現,主要涉及的技術包括:Urllib庫、正則表達式、Selenium、BeautifulSoup、Scrapy等技術。
網頁抓取。確定好爬取技術後,需要分析網頁的DOM樹結構,通過XPATH技術定位網頁所爬取內容的節點,再抓取數據;同時,部分網站涉及到頁面跳轉、登錄驗證等。
存儲技術。數據存儲技術主要是存儲爬取的數據信息,主要包括SQL資料庫、純文本格式、CSV\XLS文件等。
作者希望大家能從基礎跟著我學習Python知識,最後能抓取你需要的數據集並進行深入的分析,一起加油吧!
二.正則表達式正則表達式是用於處理字符串的強大工具,通常被用來檢索、替換那些符合某種規則的文本。這篇文章首先引入正則表達式的基本概念,然後講解其常用的方法,並結合Python網絡數據爬取常用模塊和常見正則表達式的網站分析方法進行講解,最後使用正則表達式爬取了個人博客網站。
正則表達式(Regular Expression,簡稱Regex或RE)又稱為正規表示法或常規表示法,常常用來檢索、替換那些符合某個模式的文本,它首先設定好了一些特殊的字符及字符組合,通過組合的「規則字符串」來對表達式進行過濾,從而獲取或匹配我們想要的特定內容。它非常靈活,其邏輯性和功能性也非常強,能迅速地通過表達式從字符串中找到所需信息,但對剛接觸的人來說,比較晦澀難懂。
由於正則表達式主要應用對象是文本,因此它在各種文本編輯器中都有應用,小到著名編輯器EditPlus,大到Microsoft Word、Visual Studio等大型編輯器,都可以使用正則表達式來處理文本內容。
1.re模塊Python通過re模塊提供對正則表達式的支持,但在使用正則表達式之前需要導入re模塊,才能調用該模塊的功能函數。
其基本步驟是先將正則表達式的字符串形式編譯為Pattern實例,然後使用Pattern實例處理文本並獲得一個匹配(match)實例,再使用match實例獲得所需信息。常用的函數是findall,原型如下:
findall(string[, pos[, endpos]]) |
re.findall(pattern, string[, flags])
該函數表示搜索字符串string,以列表形式返回全部能匹配的子串。其中參數re包括三個常見值,每個常見值括號內的內容是完整的寫法。
re.I(re.IGNORECASE):使匹配忽略大小寫
re.M(re.MULTILINE):允許多行匹配
re.S(re.DOTALL):匹配包括換行在內的所有字符
Pattern對象是一個編譯好的正則表達式,通過Pattern提供的一系列方法可以對文本進行匹配查找。Pattern不能直接實例化,必須使用re.compile()進行構造。
2.complie方法re正則表達式模塊包括一些常用的操作函數,比如complie()函數。其原型如下:
該函數根據包含正則表達式的字符串創建模式對象,返回一個pattern對象。參數flags是匹配模式,可以使用按位或「|」表示同時生效,也可以在正則表達式字符串中指定。Pattern對象是不能直接實例化的,只能通過compile方法得到。
簡單舉個實例,使用正則表達式獲取字符串中的數字內容,如下所示:
>>> import re
>>> string="A1.45,b5,6.45,8.82"
>>> regex = re.compile(r"\d+\.?\d*")
>>> print regex.findall(string)
['1.45', '5', '6.45', '8.82']
>>>
3.match方法match方法是從字符串的pos下標處起開始匹配pattern,如果pattern結束時已經匹配,則返回一個match對象;如果匹配過程中pattern無法匹配,或者匹配未結束就已到達endpos,則返回None。該方法原型如下:
match(string[, pos[, endpos]]) |
re.match(pattern, string[, flags])
參數string表示字符串;pos表示下標,pos和endpos的默認值分別為0和len(string);參數flags用於編譯pattern時指定匹配模式。
4.search方法search方法用於查找字符串中可以匹配成功的子串。從字符串的pos下標處嘗試匹配pattern,如果pattern結束時仍可匹配,則返回一個match對象;若pattern結束時仍無法匹配,則將pos加1後重新嘗試匹配;直到pos=endpos時仍無法匹配則返回None。函數原型如下:
search(string[, pos[, endpos]]) |
re.search(pattern, string[, flags])
參數string表示字符串;pos表示下標,pos和endpos的默認值分別為0和len(string));參數flags用於編譯pattern時指定匹配模式。
5.group和groups方法group([group1, …])方法用於獲得一個或多個分組截獲的字符串,當它指定多個參數時將以元組形式返回,沒有截獲字符串的組返回None,截獲了多次的組返回最後一次截獲的子串。groups([default])方法以元組形式返回全部分組截獲的字符串,相當於多次調用group,其參數default表示沒有截獲字符串的組以這個值替代,默認為None。
三.Python網絡數據爬取的常用模塊本小節介紹Python網絡數據爬取的常用模塊或庫,主要包括urlparse模塊、urllib模塊、urllib2模塊和requests模塊,這些模塊中的函數都是基礎知識,但也非常重要。
1.urllib模塊本書首先介紹Python網絡數據爬取最簡單並且應用比較廣泛的第三方庫函數urllib。urllib是Python用於獲取URL(Uniform Resource Locators,統一資源定址器)的庫函數,可以用來抓取遠程數據並保存,甚至可以設置消息頭(header)、代理、超時認證等。
urllib模塊提供的上層接口讓我們像讀取本地文件一樣讀取www或ftp上的數據。它比C++、C#等其他程式語言使用起來更方便。其常用的方法如下:
該方法用於創建一個遠程URL的類文件對象,然後像本地文件一樣操作這個類文件對象來獲取遠程數據。參數url表示遠程數據的路徑,一般是網址;參數data表示以post方式提交到url的數據;參數proxies用於設置代理。urlopen返回一個類文件對象。urlopen提供了如下表所示。
注意,在Python中我們可以導入相關擴展包,通過help函數查看相關的使用說明,如下圖所示。
下面通過一個實例講述Urllib庫函數爬取百度官網的實例。
import urllib.requestimport webbrowser as web
url = "http://www.baidu.com"content = urllib.request.urlopen(url)
print(content.info()) print(content.geturl()) print(content.getcode())
open("baidu.html","wb").write(content.read())web.open_new_tab("baidu.html")該段調用調用urllib.urlopen(url)函數打開百度連結,並輸出消息頭、url、http狀態碼等信息,如下圖所示。
代碼import webbrowser as web引用webbrowser第三方庫,然後可以使用類似於「modulename.method」調用對應的函數。open().write()表示在本地創建靜態的baidu.html文件,並讀取已經打開的百度網頁內容,執行文件寫操作。web.opennew_tab("baidu.html")表示通過瀏覽器打開已經下載的靜態網頁新標籤。其中下載並打開的百度官網靜態網頁「baidu.html」文件如下圖所示。
同樣可以使用下列代碼在瀏覽器中直接打開在線網頁。
web.opennewtab("http://www.baidu.com")urlretrieve
urlretrieve(url, filename=None,
reporthook=None, data=None)
urlretrieve方法是將遠程數據下載到本地。參數filename指定了保存到本地的路徑,如果省略該參數,urllib會自動生成一個臨時文件來保存數據;參數reporthook是一個回調函數,當連接上伺服器,相應的數據塊傳輸完畢時會觸發該回調,通常使用該回調函數來顯示當前的下載進度;參數data指傳遞到伺服器的數據。下面通過例子來演示將新浪首頁網頁抓取到本地,保存在「D:/sina.html」文件中,同時顯示下載進度。
import urllib.request def Download(a, b, c): per = 100.0 * a * b / c if per > 100: per = 100 print('%.2f' % per)url = 'http://www.sina.com.cn'local = 'd://sina.html'urllib.request.urlretrieve(url, local, Download)上面介紹了urllib模塊中常用的兩個方法,其中urlopen()用於打開網頁,urlretrieve()方法是將遠程數據下載到本地,主要用於爬取圖片。注意,Python2可以直接引用,而Python3需要通過urllib.request調用。
抓取百度logo圖片如下圖所示:
2.urlparse模塊urlparse模塊主要是對url進行分析,其主要操作是拆分和合併url各個部件。它可以將url拆分為6個部分,並返回元組,也可以把拆分後的部分再組成一個url。主要有函數有urljoin、urlsplit、urlunsplit、urlparse等。
urlparse
urlparse.urlparse(urlstring[,
scheme[, allow_fragments]])
該函數將urlstring值解析成6個部分,從urlstring中取得url,並返回元組(scheme, netloc, path, params, query, fragment)。該函數可以用來確定網絡協議(HTTP、FTP等)、伺服器地址、文件路徑等。實例代碼如下所示。
輸出如下所示,包括scheme、netloc、path、params、query、fragment六部分內容。
>>>
ParseResult(
scheme='http',
netloc='www.eastmount.com',
path='/index.asp',
params='',
query='id=001',
fragment=''
)
www.eastmount.com
>>>
同樣可以調用urlunparse()函數將一個元組內容構建成一條Url。函數如下:
該元組類似urlparse函數,它接收元組(scheme, netloc, path, params, query, fragment)後,會重新組成一個具有正確格式的url,以便供Python的其他HTML解析模塊使用。示例代碼如下:
輸出如下圖所示。
四.正則表達式抓取網絡數據的常見方法接著介紹常用的正則表達式抓取網絡數據的一些技巧,這些技巧都是來自於作者自然語言處理和數據抓取的項目經驗,可能不是很系統,但也希望能給讀者提供一些抓取數據的思路,從而更好地解決一些實際問題。
1.抓取標籤間的內容HTML語言是採用標籤對的形式來編寫網站的,包括起始標籤和結束標籤,比如< head>、< tr>、< script>< script>等。下面講解抓取標籤對之間的文本內容,比如抓取< title>Python標籤對之間的「Python」內容。
(1) 抓取title標籤間的內容
'<title>(.*?)</title>'
首先我們可以採用該正則表達式來抓取起始標籤< title >和結束標籤< /title >之間的內容,「(.*?)」就代表著我們需要抓取的內容。下面這段代碼是爬取百度官網的標題,即「百度一下,你就知道」。
import re import urllib.requesturl = "http://www.baidu.com/" content = urllib.request.urlopen(url).read()title = re.findall(r'<title>(.*?)</title>', content.decode('utf-8'))print(title[0])代碼調用urllib庫的urlopen()函數打開超連結,並調用正則表達式re庫中的findall()函數尋找title標籤間的內容。由於findall()函數是獲取所有滿足該正則表達式的文本,這裡只需要輸出第一個值title[0]即可。注意,Python3需要轉換utf8編碼,否則會報錯。
下面講解另一種方法,用來獲取標題起始標籤(< title>)和結束標籤()之間的內容,同樣輸出百度官網標題「百度一下,你就知道」。
import re import urllib.request
url = "http://www.baidu.com/" content = urllib.request.urlopen(url).read()pat = r'(?<=<title>).*?(?=</title>)' ex = re.compile(pat, re.M|re.S)obj = re.search(ex, content.decode('utf-8'))title = obj.group() print(title)(2) 抓取超連結標籤間的內容
在HTML中,< a href=url>超連結標題用於標識超連結,下面的代碼用於獲取完整的超連結,同時獲取超連結< a>和之間的標題內容。
import re import urllib.requesturl = "http://www.baidu.com/" content = urllib.request.urlopen(url).read()
res = r"<a.*?href=.*?<\/a>"urls = re.findall(res, content.decode('utf-8'))for u in urls: print(u)
res = r'<a .*?>(.*?)</a>' texts = re.findall(res, content.decode('utf-8'), re.S|re.M) for t in texts: print(t)輸出結果部分內容如下所示,這裡如果採用「print(u)」或「print(t)」語句直接輸出結果。
(3) 抓取tr標籤和td標籤間的內容
網頁常用的布局包括table布局或div布局,其中table表格布局中常見的標籤包括tr、th和td,表格行為tr(table row),表格數據為td(table data),表格表頭為th(table heading)。那麼如何抓取這些標籤間的內容呢?下面是獲取它們之間內容的代碼。假設存在HTML代碼如下所示:
運行結果如下圖所示:
正則表達式爬取tr、th、td標籤之間內容的Python代碼如下。
輸出結果如下,首先獲取tr之間的內容,然後再在tr之間內容中獲取< th>和之間值,即「學號」、「姓名」,最後是獲取兩個< td>和之間的內容。注意,Python3解析本地文件可能會出錯,掌握方法更重要。
如果包含屬性值,則正則表達式修改為「< td id=.?>(.?)」。同樣,如果不一定是id屬性開頭,則可以使用正則表達式「(.*?)」。
2.爬取標籤中的參數(1) 抓取超連結標籤的url
HTML超連結的基本格式為「< a href=url>連結內容」,現在需要獲取其中的url連結地址,方法如下:
輸出內容如下:
(2) 抓取圖片超連結標籤的url
在HTML中,我們可以看到各式各樣的圖片,其圖片標籤的基本格式為「< img src=圖片地址 />」,只有通過抓取了這些圖片的原地址,才能下載對應的圖片至本地。那麼究竟怎麼獲取圖片標籤中的原圖地址呢?下面這段代碼就是獲取圖片連結地址的方法。
原圖地址為「http://../eastmount.jpg」,它對應一張圖片,該圖片是存儲在「www.yangxiuzhang.com」網站伺服器端的,最後一個「/」後面的欄位為圖片名稱,即為「eastmount.jpg」。那麼如何獲取url中最後一個參數呢?
(3) 獲取url中最後一個參數
在使用Python爬取圖片過程中,通常會遇到圖片對應的url最後一個欄位用來命名圖片的情況,如前面的「eastmount.jpg」,需要通過解析url「/」後面的參數來獲取圖片。
該段代碼urls.split('/')[-1]表示採用字符「/」分割字符串,並且獲取最後一個所獲取的值,即為圖片名稱「eastmount.jpg」。
3.字符串處理及替換在使用正則表達式爬取網頁文本時,通常需要調用find()函數找到指定的位置,再進行進一步爬取,比如獲取class屬性為「infobox」的表格table,再進行定位爬取。
同時,爬取過程中可能會爬取到無關變量,此時需要對無關內容進行過濾,這裡推薦使用replace函數和正則表達式進行處理。比如爬取內容如下所示:
輸出內容如下所示:
此時需要過濾多餘字符串,如換行(< br />)、空格(& nbsp;)、加粗(< B>),過濾代碼如下:
採用replace將字符串「< br />」和「'& nbsp;」替換成空白,實現過濾,而加粗(< B>)需要使用正則表達式過濾。輸出結果如下:
五.個人博客爬取實例切記:這個例子可能不是非常好,但是作為入門及正則表達式結合挺好的。剛開始學習Python網絡爬蟲不要嫌麻煩,只有通過類似的訓練,以後面對類似的問題你才會得心應手,更好的抓取需要的數據。
1.分析過程在講述了正則表達式、常用網絡數據爬取模塊、正則表達式爬取數據常見方法等內容之後,我們將講述一個簡單的正則表達式爬取網站的實例。這裡講解使用正則表達式爬取作者個人博客網站的簡單示例,獲取所需內容。
作者的個人網址打開如圖所示。假設現在需要爬取的內容如下:
博客網址的標題(title)內容
爬取所有圖片的超連結,比如爬取< img src=」xxx.jpg」 />中的「xxx.jpg」
分別爬取博客首頁中的四篇文章的標題、超連結及摘要內容,比如標題為「再見北理工:憶北京研究生的編程時光」
http://www.eastmountyxz.com/
第一步 瀏覽器源碼定位
首先通過瀏覽器定位需要爬取元素的原始碼,比如文章標題、超連結、圖片等,發現這些元素對應HTML原始碼存在的規律,這稱為DOM樹文檔節點分析。通過瀏覽器打開網頁,選中需要爬取的內容,右鍵滑鼠並點擊「審查元素」或「檢查」,即可找到所需爬取節點對應的HTML原始碼,如圖所示。
標題「再見北理工:憶北京研究生的編程時光」位於< div class=」essay」>節點下,它包括一個< h1>記錄標題,一個< p>記錄摘要信息,即:
這裡需要通過網頁標籤的屬性和屬性值來標記爬蟲節點,即找到class屬性為「essay」的div,就可以定位第一篇文章的位置。同理,其餘三篇文章為< div class=」essay1」>、< div class=」essay2」>和< div class=」essay3」>,定位這些節點即可。
第二步 正則表達式爬取標題
網站的標題通常位於< head>< title>...之間,該網站標題HTML代碼如下:
<head>
<meta charset=」utf-8」>
<title>秀璋學習天地</title>
....
</head>
爬取博客網站的標題「秀璋學習天地」的方法是通過正則表達式「< title>(.*?)」實現,代碼如下,首先通過urlopen()函數訪問博客網址,然後定義正則表達式爬取。
import reimport urllib.request
url = "http://www.eastmountyxz.com/"content = urllib.request.urlopen(url).read()title = re.findall(r'<title>(.*?)</title>', content.decode('utf-8'))print(title[0])輸出結果如下圖所示:
第三步 正則表達式爬取所有圖片地址
由於HTML插入圖片標籤格式為「< img src=圖片地址 />」,則使用正則表達式獲取圖片地址的方法為:獲取以「src=」開頭,以雙引號結尾的內容即可。代碼如下:
輸出的結果如下所示,共顯示了6張圖片。
需要注意:這裡的每張圖片都省略了博客地址:
我們需要對所爬取的圖片地址進行拼接,增加原博客地址拼成完整的圖片地址,再進行下載,並且該地址通過瀏覽器可以直接訪問查看。如:
第四步 正則表達式爬取博客內容
前面第一步講述了如何定位四篇文章的標題,第一篇文章位於< div class=」essay」>和標籤之間,第二篇位於< div class=」essay1」>和,依次類推。但是該HTML代碼存在一個錯誤:class屬性通常表示一類標籤,它們的值都應該是相同的,所以這四篇文章的class屬性都應該是「essay」,而name或id才是用來標識標籤的唯一屬性。
這裡使用find('< div >')函數來定位第一篇文章的起始位置,使用find('< div >')函數來定位第一篇文章的結束位置,從而獲取< div class=」essay」>到之間的內容。比如獲取第一篇文章的標題和超連結代碼如下:
輸出內容如下,獲取第一篇博客的HTML原始碼。
該部分代碼分為三步驟:
定位這段內容之後,再通過正則表達式獲取具體內容,代碼如下:
調用正則表達式分別獲取內容,由於爬取的段落(P)存在換行內容,所以需要加入re.M和re.S支持換行查找,最後輸出結果如下:
2.代碼實現完整代碼如下:
import reimport urllib.request
url = "http://www.eastmountyxz.com/"content = urllib.request.urlopen(url).read()data = content.decode('utf-8')
title = re.findall(r'<title>(.*?)</title>', data)print(title[0])
urls = re.findall(r'src="(.*?)"', data)for url in urls: print(url)
start = data.find(r'<div>')end = data.find(r'<div>')page = data[start:end] res = r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')"t1 = re.findall(res, page) print(t1[0])t2 = re.findall(r'<a .*?>(.*?)</a>', page) print(t2[0])t3 = re.findall('<p style=.*?>(.*?)</p>', page, re.M|re.S) print(t3[0])print('')
start = data.find(r'<div>')end = data.find(r'<div>')page = data[start:end] res = r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')"t1 = re.findall(res, page) print(t1[0])t2 = re.findall(r'<a .*?>(.*?)</a>', page) print(t2[0])t3 = re.findall('<p style=.*?>(.*?)</p>', page, re.M|re.S) print(t3[0])輸出結果如圖所示。
通過上面的代碼,讀者會發現使用正則表達式爬取網站還是比較繁瑣,尤其是定位網頁節點時,後面將講述Python提供的常用第三方擴展包,利用這些包的函數進行定向爬取。
六.總結正則表達式是通過組合的「規則字符串」來對表達式進行過濾,從複雜內容中匹配想要的信息。它的主要對象是文本,適合於匹配文本字符串等內容,不適合匹配文本意義,比如匹配URL、Email這種純文本的字符就非常適合。各種程式語言都能使用正則表達式,比如C#、Java、Python等。
正則表達式爬蟲常用於獲取字符串中的某些內容,比如提取博客閱讀量和評論數的數字,截取URL域名或URL中某個參數,過濾掉特定的字符或檢查所獲取的數據是否符合某個邏輯,驗證URL或日期類型等。由於其比較靈活、邏輯性和功能性較強的特點,使它能迅速地以極簡單的方式從複雜字符串中達到匹配目的。
但它對於剛接觸的人來說,正則表達式比較晦澀難懂,但只有走過這些坑後面抓取數據才會更加得心應手。同時,通過它獲取HTML中某些特定文本也比較困難,尤其是當網頁HTML原始碼中結束標籤缺失或不明顯的情況。接下來作者將講述更為強大、智能的第三方爬蟲擴展包,主要是BeautifulSoup和Selenium等技術。
前文賞析(連結可以點喔):
最後,真誠地感謝您關注「娜璋之家」公眾號,感謝CSDN這麼多年的陪伴,會一直堅持分享,希望我的文章能陪伴你成長,也希望在技術路上不斷前行。文章如果對你有幫助、有感悟,就是對我最好的回報,且看且珍惜!2020年8月18日建立的公眾號,再次感謝您的關注,也請幫忙宣傳下「娜璋之家」,哈哈~初來乍到,還請多多指教。
(By:娜璋之家 2020-10-01 中秋國慶快樂 )
參考文獻如下: