整合營銷服務(wù)商

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

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

          MySQL學(xué)習(xí)實(shí)踐DAY07-SELECT命令—過濾

          MySQL學(xué)習(xí)實(shí)踐DAY07-SELECT命令—過濾(條件)檢索4

          習(xí)目的:對(duì)檢索的內(nèi)容進(jìn)行模糊匹配,學(xué)習(xí)使用正則表達(dá)式進(jìn)行搜索。

          學(xué)習(xí)內(nèi)容:WHERE字句的REGEXP字句。


          SELECT [column_name] FROM [table_name] WHERE [column_name] REGEXP '正則表達(dá)式';

          --正則表達(dá)式的寫法需要另外學(xué)習(xí),且MySQL支持的正則表達(dá)式也只是其子集。


          拓展內(nèi)容:

          --正則表達(dá)式是用來匹配文本的特殊的串(字符集合)。如果你想從一個(gè)文本文件中提取電話號(hào)碼,可以使用正則表達(dá)式。如果你需要查找名字中間有數(shù)字的所有文件,可以使用如果你想替換一個(gè)頁面中的所有URL為這些URL的實(shí)際HTML鏈接,也可以使用一個(gè)正則表達(dá)式所有種類的程序設(shè)計(jì)語言、文本編輯器、操作系統(tǒng)等都支持正則表達(dá)式。

          --LIKE匹配整個(gè)列。如果被匹配的文本在列值中出現(xiàn),LIKE將不會(huì)找到它,相應(yīng)的行也不被返回(除非使用通配符)。而REGEXP在列值內(nèi)進(jìn)行匹配,如果被匹配的文本在列值中出現(xiàn),REGEXP將會(huì)找到它,相應(yīng)的行將被返回。這是一個(gè)非常重要的差別。那么,REGEXP能不能用來匹配整個(gè)列值(從而起與LIKE相同的作用)?答案是肯定的,使用^和$定位符(anchor)即可。

          者 | 不愿透露姓名の網(wǎng)友

          出品 | CSDN博客

          介紹爬蟲

          1.爬蟲:自動(dòng)的抓取互聯(lián)網(wǎng)上信息的腳本文件。

          2.爬蟲可以解決的問題:

          (1)解決冷啟動(dòng)問題

          (2)搜索引擎的根基:做搜索引擎少不了爬蟲

          (3)建立知識(shí)圖譜,幫助建立機(jī)器學(xué)習(xí)知識(shí)圖譜

          (4)可以制作各種商品的比價(jià)軟件,趨勢(shì)分析。

          3.爬蟲分類

          (1)通用爬蟲:搜索引擎的主要組成,作用就是將互聯(lián)網(wǎng)的上頁面整體的爬取下來之后,保存到本地。

          (2)聚焦爬蟲:聚焦爬蟲在實(shí)施網(wǎng)頁抓取時(shí)會(huì)對(duì)內(nèi)容進(jìn)行處理篩選,盡量保證只抓取與需求相關(guān)的網(wǎng)頁信息。

          通用爬蟲和聚焦爬蟲的區(qū)別:聚焦爬蟲在實(shí)施網(wǎng)頁抓取時(shí)會(huì)對(duì)內(nèi)容進(jìn)行處理篩選,盡量保證只抓取與需求相關(guān)的網(wǎng)頁信息。

          4.爬蟲遵循的協(xié)議:robot協(xié)議

          定義:網(wǎng)絡(luò)爬蟲排除標(biāo)準(zhǔn)。

          作用:告訴搜索引擎哪里可以爬,哪里不可以爬。

          5.通用爬蟲工作流程

          (1)抓取網(wǎng)頁:通過搜索引擎將待爬取的url加入到通用爬蟲的url隊(duì)列中,進(jìn)行網(wǎng)頁內(nèi)容的爬取

          (2)數(shù)據(jù)存儲(chǔ):將爬取下來的網(wǎng)頁保存到本地,這個(gè)過程會(huì)有一定的去重操作,如果某個(gè)網(wǎng)頁的內(nèi) 容大部分內(nèi)容都會(huì)重復(fù),搜索引擎可能不會(huì)保存。

          (3)預(yù)處理:提取文字,中文分詞,消除噪音(比如版權(quán)聲明文字,導(dǎo)航條,廣告等)。

          (4)設(shè)置網(wǎng)站排名,為用戶提供服務(wù)。

          6.一些反爬及其應(yīng)對(duì)措施

          ( 1)通過user-agent來判斷是否是爬蟲。

          解決方案:可以通過偽裝請(qǐng)求頭中的user-agent來解決。若user-agent被檢測(cè)到,可以找大量的user-agent,放入列表,然后進(jìn)行更換

          (2)將IP進(jìn)行封殺。

          解決方案:可以通過代理來偽裝IP。

          (3)通過訪問頻率來判斷是否是一個(gè)爬蟲。

          解決方案:可以通過設(shè)置請(qǐng)求間隔,和爬取間隔。

          (4)當(dāng)一定時(shí)間內(nèi)的總請(qǐng)求數(shù)超過上限,彈出驗(yàn)證碼。

          解決方案:對(duì)于簡單的驗(yàn)證碼圖片可以使用tesseract來處理,對(duì)于復(fù)雜的可以去打碼平臺(tái)。

          (5)通過JS來獲取頁面數(shù)據(jù)。

          解決方案:可以使用selenium+phantomjs來加載JS獲取數(shù)據(jù)。

          介紹搜索引擎

          1.搜索引擎的主要組成

          通用爬蟲:就是將互聯(lián)網(wǎng)的上頁面整體的爬取下來之后,保存到本地。

          通用爬蟲要想爬取網(wǎng)頁,需要網(wǎng)站的url.但是搜索引擎是可以搜索所有網(wǎng)頁的。那么通用爬蟲url就要涉及到所有網(wǎng)頁,這個(gè)‘所有’是如何做到的:

          • 新網(wǎng)站向搜索引擎主動(dòng)提交網(wǎng)址;

          • 在其他網(wǎng)站上設(shè)置新網(wǎng)站外鏈;

          • 搜索引擎和DNS解析服務(wù)商(如DNSPod等)合作,新網(wǎng)站域名將被迅速抓取。

          2.搜索引擎的工作流程(通用爬蟲的工作流程)

          (1)抓取網(wǎng)頁:通過搜索引擎將待爬取的URL加入到通用爬蟲的URL隊(duì)列中,進(jìn)行網(wǎng)頁內(nèi)容的爬取。

          (2)數(shù)據(jù)存儲(chǔ):將爬取下來的網(wǎng)頁保存到本地,這個(gè)過程會(huì)有一定的去重操作,如果某個(gè)網(wǎng)頁的內(nèi) 容大部分內(nèi)容都會(huì)重復(fù),搜索引擎可能不會(huì)保存。

          (3)預(yù)處理:提取文字,中文分詞,消除噪音(比如版權(quán)聲明文字,導(dǎo)航條,廣告等)。

          (4)設(shè)置網(wǎng)站排名,為用戶提供服務(wù)。

          3.搜索引擎的局限性

          (1)搜索引擎只能爬取原網(wǎng)頁,但是頁面90%內(nèi)容都是無用的。

          (2)搜索引擎不能滿足不同行業(yè),不同人的特定需求。

          (3)通用搜索引擎只能爬取文字信息,不能對(duì)音頻、圖片等進(jìn)行爬取。

          (4)只能基于關(guān)鍵字查詢,無法基于語義查詢。

          介紹HTTP

          網(wǎng)絡(luò)七層協(xié)議:

          1.HTTP協(xié)議特點(diǎn)

          • HTTP協(xié)議是超文本傳輸協(xié)議;

          • HTTP協(xié)議是一個(gè)應(yīng)用層協(xié)議;

          • 無連接:每次請(qǐng)求都是獨(dú)立的;

          • 無狀態(tài),表示客戶端每次請(qǐng)求都不能記錄請(qǐng)求狀態(tài),就是兩條請(qǐng)求直接不可通信。

          2.HTTP工作過程

          • 地址進(jìn)行DNS解析,將URL解析出對(duì)應(yīng)的內(nèi)容

          • 封裝HTTP請(qǐng)求數(shù)據(jù)包

          • 封裝成TCP包,建立TCP連接(TCP的三次握手)

          • 客戶端發(fā)送請(qǐng)求

          • 服務(wù)器接收請(qǐng)求,發(fā)送響應(yīng)

          • 客戶端接收到響應(yīng),進(jìn)行頁面渲染

          • 服務(wù)器關(guān)閉TCP連接(TCP的四次揮手)

          3.HTTP協(xié)議和HTTPS協(xié)議的區(qū)別

          • HTTP協(xié)議是使用明文數(shù)據(jù)傳輸?shù)木W(wǎng)絡(luò)協(xié)議,明文傳輸會(huì)讓用戶存在一個(gè)非常大的安全隱患。端口80

          • HTTPS協(xié)議可以理解為HTTP協(xié)議的安全升級(jí)版,就是在HTTP的基礎(chǔ)上增加了數(shù)據(jù)加密。端口443

          • HTTPS協(xié)議是由 SSL+HTTP 協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議要比HTTP協(xié)議安全。

          4.HTTP通信

          HTTP通信由兩部分組成:客戶端請(qǐng)求消息與服務(wù)器響應(yīng)消息。

          5.關(guān)于響應(yīng)常見的響應(yīng)碼

          6.客戶端請(qǐng)求(Get和Post區(qū)別)

          (1)組成:請(qǐng)求行、請(qǐng)求頭部、空行、請(qǐng)求數(shù)據(jù)四個(gè)部分組成

          (2)請(qǐng)求方法Get/Post

          (3)Get和Post的區(qū)別

          GET和POST本質(zhì)上就是TCP鏈接,并無差別。但是由于HTTP的規(guī)定和瀏覽器/服務(wù)器的限制,導(dǎo)致他們?cè)趹?yīng)用過程中體現(xiàn)出一些不同。

          (4)常見的請(qǐng)求頭

          User-Agent:客戶端請(qǐng)求標(biāo)識(shí)。

          Accept:傳輸文件類型。

          Referer :請(qǐng)求來源。

          cookie (cookie):在做登錄的時(shí)候需要封裝這個(gè)頭。

          Content-Type (POST數(shù)據(jù)類型)

          7.服務(wù)器響應(yīng)

          (1)組成:狀態(tài)行,響應(yīng)頭,空行,響應(yīng)正文。

          (2)常見的響應(yīng)頭

          Content-Type:text/html;資源文件的類型,還有字符編碼

          Content-Length:響應(yīng)長度

          Content-Size響應(yīng)大小

          Content-Encoding告訴客戶端,服務(wù)端發(fā)送的資源是采用什么編碼的。

          Connection:keep-alive這個(gè)字段作為回應(yīng)客戶端的Connection:keep-alive,告訴客戶端服務(wù)器的tcp連接也是一個(gè)長連接,客戶端可以繼續(xù)使用這個(gè)TCP連接發(fā)送HTTP請(qǐng)求

          url

          統(tǒng)一資源定位符:

          基本格式:scheme://host[:port#]/path/…/?query-string

          協(xié)議://服務(wù)器ip地址:端口號(hào)/資源路徑/?key1=參數(shù)1&key2=參數(shù)2

          scheme:協(xié)議(例如:HTTP、HTTPS、FTP)

          host/IP:服務(wù)器的IP地址或者域名

          port:服務(wù)器的端口(如果是走協(xié)議默認(rèn)端口,缺省端口80),用來從互聯(lián)網(wǎng)進(jìn)入電腦

          path:訪問資源的路徑,就是為了在電腦中找到對(duì)應(yīng)的資源路徑

          query-string:參數(shù),發(fā)送給http服務(wù)器的數(shù)據(jù)

          anchor:錨(跳轉(zhuǎn)到網(wǎng)頁的指定錨點(diǎn)位置)

          Q:當(dāng)我們?cè)跒g覽器輸入一個(gè)URL,為什么可以加載出一個(gè)頁面?為什么抓包的過程中請(qǐng)求一個(gè)URL,出現(xiàn)很多的資源請(qǐng)求?

          當(dāng)我們?cè)跒g覽器輸入一個(gè)URL,客戶端會(huì)發(fā)送這個(gè)URL對(duì)應(yīng)的一個(gè)請(qǐng)求到服務(wù)器獲取內(nèi)容。服務(wù)器收到這個(gè)請(qǐng)求,解析出對(duì)應(yīng)內(nèi)容,之后將內(nèi)容封裝到響應(yīng)里發(fā)送到客戶端

          當(dāng)客戶端拿到這個(gè)HTML頁面,會(huì)查看這個(gè)頁面中是否有CSS、JS、image等URL,如果有,在分別進(jìn)行請(qǐng)求,獲取到這些資源。

          客戶端會(huì)通過HTML的語法,將獲取到的所有內(nèi)容完美的顯示出來。

          Cookie和Session

          產(chǎn)生原因:由于HTTP是一個(gè)無狀態(tài)的協(xié)議,每次請(qǐng)求如果需要之前的一些信息,無法記錄,因此為了解決這個(gè)問題,產(chǎn)生了一種記錄狀態(tài)技術(shù),Cookie和Session。

          Cookie指某些網(wǎng)站為了辨別用戶身份,進(jìn)行會(huì)話跟蹤而存儲(chǔ)在用戶本地終端上的數(shù)據(jù),種類有會(huì)話Cookie和持久Cookie。

          (1)會(huì)話Cookie指存在瀏覽器內(nèi)存的Cookie,當(dāng)瀏覽器關(guān)閉,會(huì)話Cookie會(huì)失效;

          (2)持久Cookie是保存在硬盤上的Cookie。

          Session用來存儲(chǔ)特定的用戶會(huì)話所需的屬性及其配置信息。

          Cookie是在客戶端記錄狀態(tài),Session是在服務(wù)端記錄狀態(tài)。

          聯(lián)系:當(dāng)客戶端發(fā)送一個(gè)Cookie,服務(wù)器會(huì)從這個(gè)Cookie中找到sessionID,再查找出相應(yīng)的Session信息返回給客戶端,來進(jìn)行用戶頁面的流轉(zhuǎn)。如果通過sessionID來查找Session的時(shí)候,發(fā)現(xiàn)沒有Session(一般第一次登陸或者清空了瀏覽器),那么就會(huì)創(chuàng)建一個(gè)Session。

          hashlib密碼加密

          def get_hex(value):

          md5_=hashlib.md5

          md5_.update(value.encode('utf-8'))

          return md5_.hexdigest

          關(guān)于response.text亂碼問題

          response的常用屬性:

          1.獲取字符串類型的響應(yīng)正文:response.text

          2.獲取bytes類型的響應(yīng)正文:response.content

          3.響應(yīng)正文字符串編碼:response.encoding

          4.狀態(tài)碼:response.status_code

          5.響應(yīng)頭:response.headers

          response.text亂碼問題:

          #方法一:轉(zhuǎn)換成utf-8格式

          response.encoding='utf-8'

          print(response.text)

          #方法二:解碼為utf-8 :

          with open('index.html','w',encoding='utf-8') as fp: fp.write(response.content.decode('utf-8'))


          代理

          代理的作用:

          1、突破自身IP 訪問限制, 訪問一些平時(shí)不能訪問的站點(diǎn)。

          2、訪問一些單位或團(tuán)體內(nèi)部資源:比如使用教育網(wǎng)內(nèi)地址段免費(fèi)代理服務(wù)器, 就可以用于對(duì)教育網(wǎng)開放的各類FTP 下載上傳, 以及各類資料查詢共享等服務(wù)。

          3、提高訪問速度:通常代理服務(wù)器都設(shè)置一個(gè)較大的硬盤緩沖區(qū),當(dāng)有外界的信息通過時(shí), 同時(shí)也將其保存到緩沖區(qū)中,當(dāng)其他用戶再訪問相同的信息時(shí),則直接由緩沖區(qū)中取屮信息傳給用戶,以提高訪問速度。

          4、隱藏真實(shí)IP :上網(wǎng)者也可以通過這種方法隱藏自己的IP , 免受攻擊。對(duì)于爬蟲來說, 我們用代理就是為了隱藏自身IP , 防止自身的被封鎖。

          代理根據(jù)匿名程度的分類:

          JSON數(shù)據(jù)

          數(shù)據(jù)的分類:

          JSON的本質(zhì):是一個(gè)字符串,JSON是對(duì)JS對(duì)象的字符串表達(dá)式,它使用文本形式表示一個(gè)JS對(duì)象的信息。

          JSON使用:

          (1)json.dumps(Python的list或者dict),將Python的list或者dict返回為一個(gè)JSON字符串;

          (2)json.loads(json字符串),將JSON字符串返回為Python的list或者dict;

          (3)json.dump(list/dict,fp),將Python的list或者dict轉(zhuǎn)為一個(gè)JSON字符串,保存到文件中;

          (4)json.load(fp) ,從JSON文件中讀出JSON數(shù)據(jù),并轉(zhuǎn)換為Python的list或者dict。

          正則表達(dá)式

          1、貪婪和非貪婪

          (1)正則默認(rèn)是貪婪模式,所以數(shù)量控制符默認(rèn)是取最大值,也是貪婪。例如*

          (2)非貪婪是用?來控制,盡量匹配最少的次數(shù),0次或一次。

          2、Python使用格式:

          pattern=re.compile('正則表達(dá)式') 

          print(pattern.match(字符串,start,end))#默認(rèn)從頭開始匹配,只匹配一次,返回一個(gè)match對(duì)象

          print(pattern.search(字符串,start,end))#從任意位置開始匹配,只匹配一次,返回一個(gè)match對(duì)象

          print(pattern.findall(字符串,start,end))#全文多次匹配,將匹配到的結(jié)果放到一個(gè)list返回給我們

          print(pattern.finditer(字符串,start,end))#全文多次匹配,將匹配到的結(jié)果放到一個(gè)match對(duì)象的迭代器返回

          3、常見的正則題目

          XML

          XML的基本知識(shí):

          1.定義:XML稱為可拓展性標(biāo)記語言,類似 HTML;

          2.特點(diǎn):XML具有自描述特性,是一種半結(jié)構(gòu)化數(shù)據(jù);

          3.作用:XML的設(shè)計(jì)宗旨是傳輸數(shù)據(jù),而非顯示數(shù)據(jù)。可以作為配置文件使用來記錄一些重要信息;

          4.XML的標(biāo)簽需要我們自行定義。

          HTML和XML 區(qū)別:

          語法方面:

          • 在HTML中不區(qū)分大小寫,在XML中嚴(yán)格區(qū)分大小寫

          • 在HTML中,在某些情況可以省略閉合標(biāo)簽。在XML中,絕對(duì)不能省略任何標(biāo)記。

          • 在XML中,單標(biāo)簽結(jié)尾處需要加’/’。

          • XML文檔中,空白部分不會(huì)被解析器自動(dòng)刪除,但是HTML是過濾掉空格的

          • 在XML中,屬性值必須封裝在引號(hào)中。在HTML中,引號(hào)可用可不用。

          • 在HTML中屬性名可以不帶屬性值,XML必須帶屬性值而且不能為空。

          標(biāo)記不同:

          HTML使用固有的標(biāo)記,XML沒有固有標(biāo)記。

          作用不同:

          XML主要用來傳輸數(shù)據(jù),HTML主要用來顯示數(shù)據(jù)。

          Selenium+PhantomJS

          Selenium:Web自動(dòng)測(cè)試工具。

          PantomJS:是一個(gè)無界面的瀏覽器,所以他可以運(yùn)行JS代碼,幫我們拿到頁面數(shù)據(jù)。

          特點(diǎn):功能強(qiáng)大,幾乎可以對(duì)付任何網(wǎng)頁,但會(huì)導(dǎo)致代碼效率低。

          Selenium 是一個(gè) Web 的自動(dòng)化測(cè)試工具,可以根據(jù)我們的指令,讓瀏覽器自動(dòng)加載頁面,獲取需要的數(shù)據(jù),甚至頁面截屏,或者判斷網(wǎng)站上某些動(dòng)作是否發(fā)生。Selenium 自己不帶瀏覽器,不支持瀏覽器的功能,它需要與第三方瀏覽器結(jié)合在一起才能使用。但是我們有時(shí)候需要讓它內(nèi)嵌在代碼中運(yùn)行, 所以我們可以用一個(gè)PhantomJS 的工具代替真實(shí)的瀏覽器。Selenium 庫里有個(gè)叫 WebDriver 的 API。WebDriver 有點(diǎn)兒像可以加載網(wǎng)站的瀏覽器,但是它也可以查找頁面元素,與頁面上的元 素進(jìn)行交互 (發(fā)送文本、點(diǎn)擊等),以及執(zhí)行其他動(dòng)作來運(yùn)行網(wǎng)絡(luò)爬蟲。

          PhantomJS 是一個(gè)基于 Webkit 的“無界面”瀏覽器,它會(huì)把網(wǎng)站加載到內(nèi)存并執(zhí)行頁面上的 JavaScript,因?yàn)椴粫?huì)展示圖形界面,所以運(yùn)行起來比完整的瀏覽器要高效。相比傳統(tǒng)的 Chrome或 Firefox 瀏覽器等,資源消耗會(huì)更少。如果我們把 Selenium 和 PhantomJS 結(jié)合在一起,就可以運(yùn)行一個(gè)非常強(qiáng)大的網(wǎng)絡(luò)爬蟲了,這個(gè)爬蟲可以處理 JavaScript、Cookie、headers,以及任 何我們真實(shí)用戶需要做的事情。主程序退出后,selenium 不保證 phantomJS 也成功退出,最好手動(dòng)關(guān)閉 phantomJS 進(jìn)程。(有可能會(huì)導(dǎo)致多個(gè) phantomJS 進(jìn)程運(yùn)行,占用內(nèi)存)。WebDriverWait 雖然可能會(huì)減少延時(shí),但是目前存在 bug(各種報(bào)錯(cuò)),這種 情況可以采用 sleep。phantomJS 爬數(shù)據(jù)比較慢,可以選擇多線程。如果運(yùn)行的時(shí)候發(fā)現(xiàn)有的可 以運(yùn)行,有的不能,可以嘗試將 phantomJS 改成 Chrome。

          實(shí)現(xiàn)模擬登錄的方式有哪些

          1.直接使用已知的Cookie訪問

          先用瀏覽器登錄,獲取瀏覽器里的cookie字符串,然后封裝至請(qǐng)求頭。

          2.模擬登錄后用session保持登錄狀態(tài)

          使用session模擬登陸后,就會(huì)自動(dòng)存儲(chǔ)一個(gè)cookie次從而保持住登錄狀態(tài)。

          3.使用Selenium+PhantomJS訪問

          Selenium庫提供了find_element(s)_by_xxx的方法來找到網(wǎng)頁中的輸入框、按鈕等元素。其中xxx可以是id、name、tag_name(標(biāo)簽名)、class_name(class),也可以是xpath(xpath表達(dá)式)等等。當(dāng)然還是要具體分析網(wǎng)頁源代碼。

          線程+進(jìn)程+多線程

          關(guān)系:一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程。

          線程的順序:

          新建:線程創(chuàng)建(t=threading.Thread(target=方法名)或者線程類)

          就緒:當(dāng)啟動(dòng)線程后,線程就進(jìn)入就緒狀態(tài),就緒狀態(tài)的線程會(huì)被放到一個(gè)CPU調(diào)度隊(duì)列里面,cpu會(huì)負(fù)責(zé)讓其中的線程運(yùn)行,變?yōu)檫\(yùn)行狀態(tài)。

          運(yùn)行狀態(tài):CPU調(diào)度一個(gè)就緒狀態(tài)的線程,該線程就變?yōu)檫\(yùn)行狀態(tài)。

          阻塞狀態(tài):當(dāng)運(yùn)行狀態(tài)的線程被阻塞變?yōu)樽枞麪顟B(tài),阻塞狀態(tài)的線程就會(huì)重新變?yōu)榫途w狀態(tài)才能繼續(xù)運(yùn)行。

          死亡狀態(tài):線程執(zhí)行完畢。

          多線程和多進(jìn)程優(yōu)缺點(diǎn)

          多線程的優(yōu)點(diǎn):

          • 程序邏輯和控制方式復(fù)雜;

          • 所有線程可以直接共享內(nèi)存和變量;

          • 線程方式消耗的總資源比進(jìn)程方式好。

          多線程缺點(diǎn):

          • 每個(gè)線程與主程序共用地址空間,受限于2GB地址空間;

          • 線程之間的同步和加鎖控制比較麻煩;

          • 一個(gè)線程的崩潰可能影響到整個(gè)程序的穩(wěn)定性;

          多進(jìn)程優(yōu)點(diǎn):

          • 每個(gè)進(jìn)程互相獨(dú)立,不影響主程序的穩(wěn)定性,子進(jìn)程崩潰沒關(guān)系;

          • 通過增加CPU,就可以容易擴(kuò)充性能;

          • 每個(gè)子進(jìn)程都有2GB地址空間和相關(guān)資源,總體能夠達(dá)到的性能上限非常大 。

          多進(jìn)程缺點(diǎn):

          • 邏輯控制復(fù)雜,需要和主程序交互;

          • 需要跨進(jìn)程邊界,如果有大數(shù)據(jù)量傳送,就不太好,適合小數(shù)據(jù)量傳送、密集運(yùn)算 多進(jìn)程調(diào)度開銷比較大。

          在實(shí)際開發(fā)中,選擇多線程和多進(jìn)程應(yīng)該從具體實(shí)際開發(fā)來進(jìn)行選擇。最好是多進(jìn)程和多線程結(jié)合。

          互斥鎖和死鎖和GLF鎖

          1.互斥鎖

          定義:當(dāng)多個(gè)線程幾乎同時(shí)修改某一個(gè)共享數(shù)據(jù)的時(shí)候,需要進(jìn)行同步控制。線程同步能夠保證多個(gè)線程安全訪問“競爭資源”,最簡單的同步機(jī)制就是引用互斥鎖。

          由于線程共享進(jìn)程的內(nèi)存空間和數(shù)據(jù),因此在某個(gè)線程要共享數(shù)據(jù)時(shí),先將其鎖定,此時(shí)資源的狀態(tài)為“鎖定”,其他線程不能更改;直到該線程釋放資源,將資源的狀態(tài)變成“非鎖定”,其他的線程才能再次鎖定該資源。互斥鎖保證了每次只有一個(gè)線程進(jìn)入寫入操作,從而保證了多線程情況下數(shù)據(jù)的正確性。互斥鎖體現(xiàn)的就是一個(gè)同步的機(jī)制,即該線程釋放資源就是一個(gè)條件,條件完成,才能執(zhí)行下一步操作。是微觀的操作。

          鎖的好處:

          (1)確定了某段代碼只能由一個(gè)線程從頭到尾完整地執(zhí)行。

          (2)全局變量的安全

          鎖的壞處:

          (1)阻止了多線程的并發(fā)執(zhí)行,包含鎖的某段代碼實(shí)際上只能以單線程模塊執(zhí)行,效率降低

          (2)由于可以存在多個(gè)鎖,不同的線程持有不同的鎖,并試圖獲取對(duì)方持有的鎖的時(shí),可能會(huì)造成“死鎖”。

          2.死鎖

          (1)同一個(gè)線程先后兩次調(diào)用lock,在第二次調(diào)用時(shí),由于鎖已經(jīng)被自己占用,該線程會(huì)掛起等待自己釋放鎖,由于該線程已被掛起而沒有機(jī)會(huì)釋放鎖,因此 它將一直處于掛起等待狀態(tài),變?yōu)樗梨i;

          (2)線程A獲得了鎖1,線程B獲得了鎖2,這時(shí)線程A調(diào)用lock試圖獲得鎖2,結(jié)果是需要掛起等待線程B釋放鎖2,而這時(shí)線程B也調(diào)用lock試圖獲得鎖1,結(jié)果是需要掛起等待線程A釋放鎖1,于是線程A和B都在等待對(duì)方釋放自己才釋放,從而造成兩個(gè)都永遠(yuǎn)處于掛起狀態(tài),造成死鎖。

          3.有GLF鎖為什么還要有互斥鎖

          (1)為什么設(shè)計(jì)GLF鎖?

          Python 在設(shè)計(jì)之初就考慮到要在解釋器的主循環(huán)中,同時(shí)只有一個(gè)線程在執(zhí)行,即在任意時(shí)刻,只有一個(gè)線程在解釋器中運(yùn)行。對(duì)Python 虛擬機(jī)的訪問由全局解釋器鎖(GIL)來控制,正是GIL鎖能保證同一時(shí)刻只有一個(gè)線程在運(yùn)行。

          (2)宏觀微觀考慮GLF鎖?

          GIL是宏觀的操作。比如在一個(gè)4核的環(huán)境下,只有一個(gè)核是運(yùn)行著線程,而其他三個(gè)核是空的。GIL是線程鎖,針對(duì)線程,而不是進(jìn)程。

          MongoDB

          MongoDB和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫區(qū)別:

          1.傳統(tǒng)數(shù)據(jù)庫特點(diǎn)是存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù),數(shù)據(jù)以行為單位,每行的數(shù)據(jù)結(jié)構(gòu)和類型相同。

          2.MongoDB存儲(chǔ)的是文檔,每個(gè)文檔得結(jié)構(gòu)可以不相同,能夠更便捷的獲取數(shù)據(jù)。

          3.MongoDB的集合不需要提前創(chuàng)建,可隱式創(chuàng)建,而關(guān)系型數(shù)據(jù)庫的表需要提前定義。

          4.MongoDB第三方支持豐富。(這是與其他的NoSQL相比,MongoDB也具有的優(yōu)勢(shì))。

          5.MongoDB不支持事務(wù)操作。

          6.MongoDB支持大容量的存儲(chǔ),占用空間過大。

          MongoDB和SQL的對(duì)比:

          游標(biāo):

          定義:由于MongoDB底層是JS編寫,因此可以使用一些JS代碼,通俗的說游標(biāo)不是查詢結(jié)果,而是查詢的返回資源或者接口,就像Python中的生成器,通過這個(gè)生成器,可以一次一次的獲取每一個(gè)資源。

          持久化:日志和快照對(duì)比

          快照和日志兩者如何選擇?

          推薦兩種共同使用:

          1.如果Redis僅僅是用來做為緩存服務(wù)器的話,我們可以不使用任何的持久化。

          2.一般情況下我們會(huì)將兩種持久化的方式都開啟。redis優(yōu)先加載AOF文件來回復(fù)數(shù)據(jù)。RDB的好處是快速。

          3.在主從節(jié)點(diǎn)中,RDB作為我們的備份數(shù)據(jù),只在salve(從節(jié)點(diǎn))上啟動(dòng),同步時(shí)間可以設(shè)置的長一點(diǎn),只留(save 900 1)這條規(guī)則就可以了。

          4.開啟AOF的情況下,主從同步是時(shí)候必然會(huì)帶來IO的性能影響,此時(shí)我們可以調(diào)大auto-aof-rewrite-min-size的值,比如5GB。來減少IO的頻率

          5.不開啟AOF的情況下,可以節(jié)省IO的性能影響,這是主從間通過RDB持久化同步,但如果主從都掛掉,影響較大。

          在dump rdb過程中,aof如果停止同步,會(huì)不會(huì)丟失?

          答: 不會(huì),所有的操作緩存在內(nèi)存的隊(duì)列里,dump完成后,統(tǒng)一操作。

          aof重寫是指什么?

          答:由于日志保存的是所有操作命令,導(dǎo)致存的日志會(huì)過大,而且數(shù)據(jù)庫中有可能數(shù)據(jù)進(jìn)行過刪除,因此日志中的一些命令就相當(dāng)于無效,因此日志先會(huì)刪除,然后內(nèi)存中的數(shù)據(jù)會(huì)逆化成命令,再重新寫入到日志文件中,以解決 aof日志過大的問。

          如果rdb文件和aof文件都存在,優(yōu)先用誰來恢復(fù)數(shù)據(jù)?

          答: 在這種情況下,當(dāng)Redis重啟的時(shí)候會(huì)優(yōu)先載入AOF文件來恢復(fù)原始的數(shù)據(jù),因?yàn)樵谕ǔG闆r下AOF文件保存的數(shù)據(jù)集要比RDB文件完整。

          恢復(fù)時(shí)rdb和aof哪個(gè)恢復(fù)的快?

          答: rdb快,因?yàn)槠涫菙?shù)據(jù)的內(nèi)存映射,直接載入到內(nèi)存,而aof是命令,需要逐條執(zhí)行。

          Scrapy和Scrapy-Redis

          什么是Scrapy?

          Scrapy 是一個(gè)快速、高層次的基于 Python 的 Web 爬蟲構(gòu)架,它用于抓取Web 站點(diǎn)并從頁面中提取結(jié)構(gòu)化的數(shù)據(jù)。Scrapy 使用了 Twisted異步網(wǎng)絡(luò)庫來處理網(wǎng)絡(luò)通訊。

          Scrapy 常應(yīng)用在包括數(shù)據(jù)挖掘,信息處理或存儲(chǔ)歷史數(shù)據(jù)等一系列的程序中。

          Scrapy優(yōu)缺點(diǎn)

          優(yōu)點(diǎn):

          • Scrapy 是異步的(Scrapy 框架的異步機(jī)制是基于 twisted 異步網(wǎng)絡(luò)框架處理的,在 settings.py 文件里可以設(shè)置具體的并發(fā)量數(shù)值(默認(rèn)是并發(fā)量 16))

          • 采取可讀性更強(qiáng)的xpath代替正則

          • 強(qiáng)大的統(tǒng)計(jì)和log系統(tǒng)

          • 同時(shí)在不同的url上爬行

          • 支持shell方式,方便獨(dú)立調(diào)試

          • 寫middleware,方便寫一些統(tǒng)一的過濾器

          • 通過管道的方式存入數(shù)據(jù)庫

          缺點(diǎn):

          • 基于Python的爬蟲框架,擴(kuò)展性比較差

          • 基于twisted框架,運(yùn)行中的exception是不會(huì)干掉reactor,并且異步框架出錯(cuò)后是不會(huì)停掉其他任務(wù)的,數(shù)據(jù)出錯(cuò)后難以察覺。

          Scrapy的組件:

          Scrapy和scrapy-redis的區(qū)別:

          Scrapy是一個(gè)Python爬蟲框架,爬取效率極高,具有高度定制性,但是不支持分布式。而scrapy-redis一套基于redis數(shù)據(jù)庫、運(yùn)行在Scrapy框架之上的組件,可以讓scrapy支持分布式策略,Slaver端共享Master端Redis數(shù)據(jù)庫里的item隊(duì)列、請(qǐng)求隊(duì)列和請(qǐng)求指紋集合

          為什么選擇Redis數(shù)據(jù)庫,因?yàn)镽edis支持主從同步,而且數(shù)據(jù)都是緩存在內(nèi)存中的,所以基于Redis的分布式爬蟲,對(duì)請(qǐng)求和數(shù)據(jù)的高頻讀取效率非常高。

          Redis的優(yōu)點(diǎn):

          1.數(shù)據(jù)讀取快,因?yàn)閿?shù)據(jù)都放在內(nèi)存上

          2.支持事務(wù)watch

          3.數(shù)據(jù)持久化,支持快照和日志,方便恢復(fù)數(shù)據(jù)

          4.擁有豐富的數(shù)據(jù)類型:list,string,set,qset,hash

          5.支持主從復(fù)制,可以進(jìn)行數(shù)據(jù)備份

          6.豐富的特性:可以作為緩存,消息隊(duì)列,設(shè)置過期時(shí)間,到期自動(dòng)刪除

          分布式爬蟲主要解決什么問題?

          IP、帶寬、CPU、io

          Scrapy如何實(shí)現(xiàn)分布式抓取?

          可以借助scrapy_redis類庫來實(shí)現(xiàn)。

          在分布式爬取時(shí),會(huì)有master機(jī)器和slave機(jī)器,其中,master為核心服務(wù)器,slave為具體的爬蟲服務(wù)器。

          我們?cè)趍aster服務(wù)器上搭建一個(gè)Redis數(shù)據(jù)庫,并將要抓取的url存放到redis數(shù)據(jù)庫中,所有的slave爬蟲服務(wù)器在抓取的時(shí)候從redis數(shù)據(jù)庫中去鏈接,由于scrapy_redis自身的隊(duì)列機(jī)制,slave獲取的url不會(huì)相互沖突,然后抓取的結(jié)果最后都存儲(chǔ)到數(shù)據(jù)庫中。master的redis數(shù)據(jù)庫中還會(huì)將抓取過的url的指紋存儲(chǔ)起來,用來去重。相關(guān)代碼在dupefilter.py文件中的request_seen方法中可以找到。

          定時(shí)任務(wù):

          1.可以設(shè)計(jì)一個(gè)定時(shí)的類,使用時(shí)間模塊(time,datetime),比如爬取時(shí)候獲取當(dāng)前時(shí)間,再當(dāng)前時(shí)間多久后再爬取

          2.使用linux的crontab的計(jì)劃任務(wù)

          crontab -l 列出所有的定時(shí)任務(wù) 看不到配置文件中寫的定時(shí)任務(wù)

          crontab -e 新增計(jì)劃任務(wù) 跟上面的區(qū)別在于 沒有用戶名

          crontab -r 清空計(jì)劃任務(wù)

          分 時(shí) 日 月 周 命令

          舉例使用:

          * * * * * 命令 每分每時(shí)每天每月每周 執(zhí)行這個(gè)命令

          0-59 0-23 1-31 1-12 0-6 0是 周天 1-6 周一到周六

          0 2 * * * mysqldump 每天的2點(diǎn)備份數(shù)據(jù)庫

          0 2 * * 2 sync 每個(gè)周二的2點(diǎn)做數(shù)據(jù)同步

          0 8 15 * * /home/jsgz.py 每個(gè)月15號(hào)的八點(diǎn)給大家算工資

          0 */2 * * * /home/camera.py 每隔2個(gè)小時(shí)執(zhí)行一次查看攝像頭

          0 8,12,18 * * 1-5 kq.py 每周1-5 的 8點(diǎn) 12點(diǎn) 18點(diǎn) 執(zhí)行打卡

          0 8 * * * * spider.sh 每天 8點(diǎn)爬蟲


          爬蟲框架、模塊

          Python自帶:urllib,urllib2。

          urllib和urllib2模塊都做與請(qǐng)求URL相關(guān)的操作,但他們提供不同的功能。

          urllib2.:urllib2.urlopen可以接受一個(gè)Request對(duì)象或者url,(在接受Request對(duì)象時(shí)候,并以此可以來設(shè)置一個(gè)URL 的headers),urllib.urlopen只接收一個(gè)url。

          urllib 有urlencode,urllib2沒有,因此總是urllib,urllib2常會(huì)一起使用的原因

          第 三 方:Requests

          Requests是一個(gè)HTTP庫, 它只是用來,進(jìn)行請(qǐng)求,對(duì)于HTTP請(qǐng)求,他是一個(gè)強(qiáng)大的庫,下載,解析全部自己處理,靈活性更高,高并發(fā)與分布式部署也非常靈活,對(duì)于功能可以更好實(shí)現(xiàn).

          框 架:Scrapy

          Scrapy是封裝起來的框架,他包含了下載器,解析器,日志及異常處理,基于多線程, twisted的方式處理,對(duì)于固定單個(gè)網(wǎng)站的爬取開發(fā),有優(yōu)勢(shì),但是對(duì)于多網(wǎng)站爬取 100個(gè)網(wǎng)站,并發(fā)及分布式處理方面,不夠靈活,不便調(diào)整與括展。

          MyISAM 與 InnoDB

          MyISAM 與 InnoDB 兩個(gè)引擎有什么區(qū)別?

          InnoDB 支持事務(wù),MyISAM 不支持,這一點(diǎn)是非常之重要。事務(wù)是一種高級(jí)的處理方式,如果在一些列增刪改中只要哪個(gè)出錯(cuò)還可以回滾還原,而 MyISAM就不可以了。

          MyISAM 適合查詢以及插入為主的應(yīng)用,InnoDB 適合頻繁修改以及涉及到安全性較高的應(yīng)用。

          InnoDB 支持外鍵,MyISAM 不支持。

          MyISAM 是默認(rèn)引擎,InnoDB 需要指定。

          InnoDB 不支持 FULLTEXT 類型的索引。

          InnoDB 中不保存表的行數(shù),如 select count( * ) from table 時(shí),InnoDB;需要掃描一遍整個(gè)表來計(jì)算有多少行,但是 MyISAM 只要簡單的讀出保存好的行數(shù)即 可。注意的是,當(dāng) count( * )語句包含 where 條件時(shí) MyISAM 也需要掃描整個(gè)表。

          對(duì)于自增長的字段,InnoDB 中必須包含只有該字段的索引,但是在 MyISAM表中可以和其他字段一起建立聯(lián)合索引。

          清空整個(gè)表時(shí),InnoDB 是一行一行的刪除,效率非常慢。MyISAM 則會(huì)重建表。

          寫爬蟲是用多進(jìn)程好?還是多線程好? 為什么?

          IO密集型情況使用多線程;

          計(jì)算密集型情況下使用多進(jìn)程;

          IO 密集型代碼(文件處理、網(wǎng)絡(luò)爬蟲等),多線程能夠有效提升效率(單線程下有 IO 操作會(huì)進(jìn)行 IO 等待,造成不必要的時(shí)間浪費(fèi),而開啟多線程能在線程 A 等待時(shí),自動(dòng)切換到線程 B,可以不浪費(fèi) CPU 的資源,從而能提升程序執(zhí)行效率)。在實(shí)際的數(shù)據(jù)采集過程中,既考慮網(wǎng)速和響應(yīng)的問題,也需要考慮自身 機(jī)器的硬件情況,來設(shè)置多進(jìn)程或多線程。

          數(shù)據(jù)庫的優(yōu)化

          為什么要優(yōu)化?

          一個(gè)應(yīng)用吞吐量瓶頸往往出現(xiàn)在數(shù)據(jù)庫的處理速度上,隨著應(yīng)用程序的使用和業(yè)務(wù)的拓展,數(shù)據(jù)庫數(shù)據(jù)量逐漸增多,數(shù)據(jù)庫處理壓力逐漸增大,關(guān)系型數(shù)據(jù)庫數(shù)據(jù)存放在磁盤上的,讀寫速度較慢(與內(nèi)存中的數(shù)據(jù)相比)。

          優(yōu)化方式:

          • 設(shè)計(jì)表的時(shí)候嚴(yán)格根據(jù)數(shù)據(jù)庫的設(shè)計(jì)范式來設(shè)計(jì)數(shù)據(jù)庫;

          • select 后盡量不使用*;

          • 盡量不使用嵌套查詢,使用連接查詢或者where查詢;

          • sql關(guān)鍵詞盡量使用大寫;

          • 盡量使用邏輯外交不使用物理外鍵;

          • 給查詢頻繁的字段添加索引,并且遵循最左原則(盡量將首選關(guān)鍵字段放在最前邊);

          • 垂直分庫分表:把一些不經(jīng)常讀的數(shù)據(jù)或者結(jié)果復(fù)雜的表拆分成多張表,較少磁盤I/O操作;

          • 水平分庫分表:于數(shù)據(jù)量龐大的表,使用水平分庫分表;

          • 使用緩存,把經(jīng)常訪問到的數(shù)據(jù)而且不需要經(jīng)常變化的數(shù)據(jù)放在緩存中,能節(jié)約磁盤IO;

          • 優(yōu)化硬件;

          • 主從分離讀寫;采用主從復(fù)制把數(shù)據(jù)庫的讀操作和寫入操作分離開來。

          使用過的解析數(shù)據(jù)包:Xpath、正則

          怎么監(jiān)控爬蟲的狀態(tài)

          (1)使用 Python 的 STMP 包將爬蟲的狀態(tài)信心發(fā)送到指定的郵箱。

          (2)Scrapyd、pyspider

          (3)引入日志

          panads讀取數(shù)據(jù)

          import pandas as pd

          # 加載detail

          detail=pd.read_excel("./meal_order_detail.xlsx")

          # 1、直接查看方式--先后索引

          # 先列 后行的方式

          # 獲取dishes_id counts amounts dishes_name 多列數(shù)據(jù)

          res=detail[["dishes_id","counts","amounts","dishes_name"]]

          # 獲取多列的前n行

          res1=detail[["dishes_id", "counts", "amounts", "dishes_name"]][:20]

          res2=detail[["dishes_id", "counts", "amounts", "dishes_name"]].head(20)

          # res=detail[["dishes_id", "counts", "amounts", "dishes_name"]][[0,1,2,3,4]] # # 不可以的

          # res=detail["dishes_id"][[0,1,2,3,4]] # 可以的

          # print("獲取多列的結(jié)果:\n", res)

          # 2、同時(shí)索引

          # loc 只能使用名稱 ---注意:可以使用名稱切片---包含收尾

          # iloc 只能使用下標(biāo)

          res3=detail.loc[:,"dishes_id":"counts"]

          # 3、ix ---同時(shí)索引-----混合索引

          # 既可以使用名稱,也可以使用下標(biāo)

          # res=detail.ix[0:4, "dishes_id":"counts"]

          # res=detail.ix[0:4, 0:2] # 前面行使用名稱,列使用下標(biāo)

          #

          # res=detail.ix[0:4, 0:"amounts"] # 錯(cuò)誤的,不能混搭

          # print("res:\n", res)



          # 直接索引方式 # 速度最快

          # loc iloc #速度適中 # 某些大的平臺(tái)上只封裝loc iloc方式 --推薦

          # ix # 速度最慢 --在最新的版本中提示,將要被刪除掉

          Nginx的正向代理和反向代理

          Web 開發(fā)中,部署方式大致類似。簡單來說,使用 Nginx 主要是為了實(shí)現(xiàn)分流、轉(zhuǎn)發(fā)、負(fù)載均衡, 以及分擔(dān)服務(wù)器的壓力。Nginx 部署簡單,內(nèi)存消耗少,成本低。Nginx 既可以做正向代理,也可以做反向代理。

          正向代理:請(qǐng)求經(jīng)過代理服務(wù)器從局域網(wǎng)發(fā)出,然后到達(dá)互聯(lián)網(wǎng)上的服務(wù)器。特點(diǎn):服務(wù)端并不知道真正的客戶端是誰。

          反向代理:請(qǐng)求從互聯(lián)網(wǎng)發(fā)出,先進(jìn)入代理服務(wù)器,再轉(zhuǎn)發(fā)給局域網(wǎng)內(nèi)的服務(wù)器。特點(diǎn):客戶端并不知道真正的服務(wù)端是誰。

          區(qū)別:正向代理的對(duì)象是客戶端。反向代理的對(duì)象是服務(wù)端。

          緩存穿透、緩存擊穿、緩存雪崩

          Redis技術(shù)就是NoSQL技術(shù)中的一種,但是引入Redis又有可能出現(xiàn)緩存穿透,緩存擊穿,緩存雪崩等問題。

          1.緩存穿透:

          (1)產(chǎn)生原因:key對(duì)應(yīng)的數(shù)據(jù)在數(shù)據(jù)源并不存在,每次針對(duì)此key的請(qǐng)求從緩存獲取不到,請(qǐng)求都會(huì)到數(shù)據(jù)源,從而可能壓垮數(shù)據(jù)源。比如用一個(gè)不存在的用戶id獲取用戶信息,不論緩存還是數(shù)據(jù)庫都沒有,若黑客利用此漏洞進(jìn)行攻擊可能壓垮數(shù)據(jù)庫。

          (2)解決方案:

          ①最常見的則是采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被這個(gè)bitmap攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。

          ②另外也有一個(gè)更為簡單粗暴的方法(我們采用的就是這種),如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù)據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過期時(shí)間會(huì)很短,最長不超過五分鐘。

          2.緩存擊穿:

          (1)產(chǎn)生原因:key對(duì)應(yīng)的數(shù)據(jù)存在,但在redis中過期,此時(shí)若有大量并發(fā)請(qǐng)求過來,這些請(qǐng)求發(fā)現(xiàn)緩存過期一般都會(huì)從后端DB加載數(shù)據(jù)并回設(shè)到緩存,這個(gè)時(shí)候大并發(fā)的請(qǐng)求可能會(huì)瞬間把后端DB壓垮。

          (2)解決方案:業(yè)界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時(shí)候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者M(jìn)emcache的ADD)去set一個(gè)mutex key,當(dāng)操作返回成功時(shí),再進(jìn)行l(wèi)oad db的操作并回設(shè)緩存;否則,就重試整個(gè)get緩存的方法。

          3.緩存雪崩:

          (1)產(chǎn)生原因:當(dāng)緩存服務(wù)器重啟或者大量緩存集中在某一個(gè)時(shí)間段失效,這樣在失效的時(shí)候,也會(huì)給后端系統(tǒng)(比如DB)帶來很大壓力。

          (2)解決方案:

          ①緩存失效時(shí)的雪崩效應(yīng)對(duì)底層系統(tǒng)的沖擊非常可怕!大多數(shù)系統(tǒng)設(shè)計(jì)者考慮用加鎖或者隊(duì)列的方式保證來保證不會(huì)有大量的線程對(duì)數(shù)據(jù)庫一次性進(jìn)行讀寫,從而避免失效時(shí)大量的并發(fā)請(qǐng)求落到底層存儲(chǔ)系統(tǒng)上。

          ②簡單方案就時(shí)講緩存失效時(shí)間分散開,比如我們可以在原有的失效時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值,比如1-5分鐘隨機(jī),這樣每一個(gè)緩存的過期時(shí)間的重復(fù)率就會(huì)降低,就很難引發(fā)集體失效的事件。

          Python垃圾回收機(jī)制

          引用計(jì)數(shù)是一種垃圾收集機(jī)制,而且也是一種最直觀,最簡單的垃圾收集技術(shù)。當(dāng) Python 的某個(gè)對(duì)象的引用計(jì)數(shù)降為 0 時(shí),說明沒有任何引用指向該對(duì)象,該對(duì)象就成為要被回收的垃圾了。比如某個(gè)新建對(duì)象,它被分配給某個(gè)引用,對(duì)象的引用計(jì)數(shù)變?yōu)?1。如果引用被刪除,對(duì)象的引用計(jì)數(shù)為 0,那么該對(duì)象就可以被垃圾回收。不過如果出現(xiàn)循環(huán)引用的話,引用計(jì)數(shù)機(jī)制就不再起有效的作用了。

          一般是類中的 __del方法進(jìn)行的。

          版權(quán)聲明:本文為CSDN博主「不愿透露姓名の網(wǎng)友」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。

          原文鏈接:https://blog.csdn.net/qq_40558166/article/details/103044923

          金三銀四招聘季,你還有哪些面試干貨文章呢?分享或者查看干貨文章可戳:

          鈕點(diǎn)擊追蹤可能是網(wǎng)站運(yùn)營中最常見的需求之一。現(xiàn)在,通過GA4 和 Google 跟蹤代碼管理器(GTM)的配合,我們可以輕易實(shí)現(xiàn)追蹤,甚至可以導(dǎo)入到google ads,輔助廣告優(yōu)化。

          具體實(shí)現(xiàn)方法有很多,本文主要介紹使用GTM的方法。

          1、獲取盡可能多的關(guān)于按鈕的信息

          首先,我們需要?jiǎng)?chuàng)建一個(gè)觸發(fā)器,或更具體地說,創(chuàng)建一個(gè)通用點(diǎn)擊觸發(fā)器。這將允許 GTM 監(jiān)聽與點(diǎn)擊相關(guān)的事件。

          在 Google 跟蹤代碼管理器中,我們可以選擇 2 個(gè)點(diǎn)擊觸發(fā)選項(xiàng):

          ? All Elements

          ? Just links

          Just links是一種常見的方式,因?yàn)樵S多按鈕本質(zhì)上是用戶點(diǎn)擊的裝飾鏈接。但是,如果您的按鈕恰好不是鏈接,您將無法獲得更多信息來跟蹤。

          這就是為什么我們喜歡使用All Elements作為觸發(fā)器類型。此觸發(fā)器類型能夠偵聽任何內(nèi)容(例如圖像、文件、按鈕、空白區(qū)域等)和鏈接上發(fā)生的點(diǎn)擊。它只是更通用、更通用。

          創(chuàng)建一個(gè)新觸發(fā)器并選擇All Elements

          現(xiàn)在,GTM 可以識(shí)別何時(shí)發(fā)生點(diǎn)擊,無論是鏈接點(diǎn)擊還是任何元素點(diǎn)擊。

          然而,我們可能需要更多的信息,而不僅僅是知道存在點(diǎn)擊交互。

          要獲取有關(guān)點(diǎn)擊的信息,請(qǐng)轉(zhuǎn)到 Google 跟蹤代碼管理器并啟用與點(diǎn)擊相關(guān)的所有內(nèi)置變量。這些變量將為我們提供所需的大部分點(diǎn)擊詳細(xì)信息,例如Click Text,它會(huì)顯示按鈕上的文本。

          在 GTM 工作區(qū)中,選擇Variables,然后選擇Configure。

          啟用所有單擊變量。

          該信息將用于創(chuàng)建觸發(fā)我們的標(biāo)簽的條件。

          返回我們的產(chǎn)品頁面,讓我們單擊Add to Cart按鈕。(在這里,添加購物車僅僅是示例,你可以把這個(gè)方法應(yīng)用在任何按鈕)

          前往 Google 跟蹤代碼管理器的調(diào)試界面。識(shí)別Summary下的Click事件并選擇它。查看之前啟用的變量向我們展示了什么信息。

          這里我們需要找到足夠獨(dú)特的數(shù)據(jù)作為觸發(fā)條件。

          2、找到獨(dú)特且可靠的數(shù)據(jù)

          在“調(diào)試”界面中,選擇左側(cè)面板中的Click事件,然后單擊Variables選項(xiàng)卡。

          重點(diǎn)關(guān)注我們已啟用的變量(Click Classes, Click ID, Click Target, Click Text, and Click URL),盡力識(shí)別按鈕特有的數(shù)據(jù)。

          通常,許多按鈕都是構(gòu)建為鏈接的,這意味著您的 Click URL 變量值很有可能顯示鏈接。您可以將其用于您的觸發(fā)條件。

          但是,很多時(shí)候并非所有維度的數(shù)據(jù)都齊全。在我們的示例中,Click URL沒有值,這時(shí)我們可以使用另外兩條信息:

          ? Click Classes,值為:single_add_to_cart_button button alt

          ? Click Text,值為: Add to cart

          需要注意的是,Click ClassesClick Text很有可能不是唯一值,該方法只適用于追蹤網(wǎng)站所有同類按鈕。

          如果我們僅僅只需要追蹤與 Ninja 產(chǎn)品的添加到購物車按鈕,怎樣才能做到這一點(diǎn)呢?

          首先,我們需要確保該按鈕是唯一的,并且在整個(gè)網(wǎng)站中不會(huì)重復(fù)。

          為此,我們將使用 Chrome 開發(fā)人員工具。如果您不熟悉,只需按照以下步驟操作即可。

          右鍵單擊您的按鈕并選擇檢查。

          這將使您能夠訪問瀏覽器的開發(fā)人員工具來查看按鈕的 HTML 和 CSS 源代碼。

          單擊鍵盤上的CTRL + F來過濾 HTML 文檔。

          復(fù)制并粘貼該類并將其粘貼到過濾器中。我們將復(fù)制粘貼single_add_to_cart_button 按鈕 alt

          過濾器將顯示您的網(wǎng)站上存在多少個(gè)此類。

          如果過濾器結(jié)果是1 of 1 ,這意味著該按鈕的類僅有唯一一項(xiàng)。使用與此按鈕相關(guān)的 GTM 點(diǎn)擊類只會(huì)跟蹤此按鈕,而不會(huì)跟蹤另一個(gè)按鈕。

          如果結(jié)果超過 1 個(gè),而您只想追蹤特定按鍵,不是同類的所有按鍵,則需要進(jìn)一步過濾。

          解決方案是在觸發(fā)器中添加頁面 URL ,以僅跟蹤位于 Flying Ninja 海報(bào)所在位置的“添加到購物車”按鈕。

          3、設(shè)置觸發(fā)器

          讓我們回到All Elements觸發(fā)器。

          默認(rèn)情況下,我們的觸發(fā)器會(huì)幫助我們檢測(cè)所有用戶點(diǎn)擊。我們需要從All Clicks切換為Some Clicks

          接下來是觸發(fā)條件的設(shè)置,在我們的例子中是:Click Classes → contains → single_add_to_cart_button

          重命名您的觸發(fā)器并保存。

          4、創(chuàng)建標(biāo)簽

          首先,我們創(chuàng)建一個(gè)新的 GA4 事件代碼。 Tag Type選擇Google Analytics: GA4 Event,再根據(jù)GA4的衡量ID對(duì)應(yīng)選擇Configuration Tag。如果沒有預(yù)設(shè)的Tag,則選擇None - Manually Set ID,再手動(dòng)填入衡量ID即可。

          然后我們需要命名我們的事件。建議button_click。遵從Google 的命名規(guī)則的最佳實(shí)踐是小寫字母加下劃線。

          此外,最好不要發(fā)明名稱,而應(yīng)該首先查看 Google 跟蹤的內(nèi)容。增強(qiáng)測(cè)量中會(huì)跟蹤點(diǎn)擊次數(shù),但沒有任何特定于按鈕點(diǎn)擊的內(nèi)容。他們將事件命名為Click,我們也可以使用它。

          此時(shí),我們可以像這樣將事件發(fā)送到 GA4。

          但是,我們希望向 GA4 發(fā)送有關(guān)此次點(diǎn)擊的更多詳細(xì)信息,因此我們將使用事件參數(shù)。

          按鈕的文本和頁面位置對(duì)我們很有價(jià)值,因此我們將添加 2 個(gè)自定義參數(shù)。

          我們的設(shè)置如下所示。

          ? 注意:我們討論的命名事件的方法與命名事件參數(shù)的方法相同。建議使用推薦事件或增強(qiáng)測(cè)量列表中任何適合您需求的事件。如果您選擇為事件參數(shù)使用自定義名稱,并且想要在 GA4 報(bào)告(自定義維度)中使用,則參數(shù)的數(shù)量將被限制為 50 個(gè)。

          Google 的推薦事件和增強(qiáng)型測(cè)量沒有與按鈕文本相關(guān)的參數(shù)。我們能找到的最接近的是link_text。link_text參數(shù)用于文件下載 。

          你也可以自定義Parameter Name。例如,button_text,甚至click_text。

          由于目標(biāo)是顯示按鈕文本的值,因此我們可以從之前啟用的Click Text變量中獲取值。

          選擇Click Text

          如果我們還想知道按鈕所在的頁面。只需重復(fù)上述過程并在Value下選擇Page頁面 URL即可。

          添加我們之前創(chuàng)建的所有觸發(fā)器。

          保存您的標(biāo)簽。

          啟用Preview模式并單擊Add to cart按鈕。

          您可以看到我們的標(biāo)簽已觸發(fā)。

          在 GA4 的 DebugView 中,您將看到即將發(fā)生的事件。

          在參數(shù)旁邊,您可以看到我們的link_textpage_location事件參數(shù)及其值。

          至此,事件創(chuàng)建已經(jīng)完成。最多不超過48小時(shí),我們就可以在GA4的事件中找到它,也可以用它創(chuàng)建轉(zhuǎn)化和受眾。


          主站蜘蛛池模板: 另类免费视频一区二区在线观看 | 性色av无码免费一区二区三区| 精品福利一区二区三区| 亚洲av成人一区二区三区在线播放| 亚洲大尺度无码无码专线一区 | 午夜视频在线观看一区二区| 国产肥熟女视频一区二区三区| 无码精品人妻一区| 亚洲欧洲一区二区| 一区二区三区四区视频在线| 亚洲永久无码3D动漫一区| 精品国产日韩亚洲一区在线 | 亚洲一区二区三区影院| 免费无码A片一区二三区| 国产美女口爆吞精一区二区| 精品一区二区三区四区在线播放| 日韩一区二区三区在线| 99久久精品午夜一区二区| 国产一区二区女内射| 日韩一区二区三区精品| 成人免费视频一区| 国产主播在线一区| 国产短视频精品一区二区三区| 精品国产毛片一区二区无码| 成人h动漫精品一区二区无码| 亚洲天堂一区二区三区| 寂寞一区在线观看| 高清国产精品人妻一区二区| 久久婷婷色综合一区二区| 国产精品亚洲不卡一区二区三区 | 麻豆aⅴ精品无码一区二区| 中文字幕永久一区二区三区在线观看| 精品一区二区三区AV天堂| 国产精品盗摄一区二区在线| 成人免费一区二区无码视频| 国模无码视频一区二区三区| 国产精品一区二区无线| 一区二区三区福利视频| 中文无码精品一区二区三区| 国产一区二区三区久久| 中文字幕一区二区三匹|