【Python】模拟面试技术面试题答
?
一、 python語(yǔ)法??
1. 請(qǐng)說(shuō)一下你對(duì)迭代器和生成器的區(qū)別?? ? ? ?
2. 什么是線程安全?? ?
3. 你所遵循的代碼規(guī)范是什么?請(qǐng)舉例說(shuō)明其要求?? ?
4. Python中怎么簡(jiǎn)單的實(shí)現(xiàn)列表去重?? ?
5. python 中 yield 的用法?? ? ? ?
6. 什么是面向?qū)ο缶幊?#xff1f;? ?
7. python2和python3的區(qū)別?? ? ?
8. 談?wù)勀銓?duì)GIL鎖對(duì)python多線程的影響???
9. python是如何進(jìn)行內(nèi)存管理的?? ?
二、 Linux基礎(chǔ)和數(shù)據(jù)結(jié)構(gòu)與算法? ??
1. 10個(gè)常用的Linux命令??
2. find和grep的區(qū)別?? ? ? ??
3. 什么是阻塞?什么是非阻塞?? ? ? ?
4. 描述數(shù)組、鏈表、隊(duì)列、堆棧的區(qū)別?? ? ? ?
5. 你知道幾種排序,講一講你最熟悉的一種?? ??
三、 Web框架? ? ??
1.django 中當(dāng)一個(gè)用戶登錄 A 應(yīng)用服務(wù)器(進(jìn)入登錄狀態(tài)),然后下次請(qǐng)求被 nginx 代理到 B 應(yīng)用服務(wù)器會(huì)出現(xiàn)什么影響?? ? ? ??
2.跨域請(qǐng)求問(wèn)題django怎么解決的(原理)? ??
3.請(qǐng)解釋或描述一下Django的架構(gòu)? ?
4.django對(duì)數(shù)據(jù)查詢結(jié)果排序怎么做,降序怎么做,查詢大于某個(gè)字段怎么做?
5.說(shuō)一下Django,MIDDLEWARES中間件的作用?? ?
6.你對(duì)Django的認(rèn)識(shí)?? ? ? ??
7. Django重定向你是如何實(shí)現(xiàn)的?用的什么狀態(tài)碼?? ?
8.ngnix的正向代理與反向代理?? ? ? ?
9. Tornado 的核是什么?? ? ?
10.Django 本身提供了 runserver,為什么不能用來(lái)部署?? ??
四、 網(wǎng)絡(luò)編程和前端??
1.AJAX是什么,如何使用AJAX?? ? ? ?
2. 常見(jiàn)的HTTP狀態(tài)碼有哪些??
3. Post和get區(qū)別?? ? ?
4.cookie 和session 的區(qū)別?? ? ?
5.創(chuàng)建一個(gè)簡(jiǎn)單tcp服務(wù)器需要的流程? ? ??
6.請(qǐng)簡(jiǎn)單說(shuō)一下三次握手和四次揮手?什么是2msl?為什么要這樣做?? ??
五、 爬蟲(chóng)和數(shù)據(jù)庫(kù)? ? ??
1.scrapy和scrapy-redis有什么區(qū)別?為什么選擇redis數(shù)據(jù)庫(kù)???
2. 你用過(guò)的爬蟲(chóng)框架或者模塊有哪些?談?wù)勊麄兊膮^(qū)別或者優(yōu)缺點(diǎn)?? ? ? ?
3.你常用的mysql引擎有哪些?各引擎間有什么區(qū)別??
4.描述下scrapy框架運(yùn)行的機(jī)制?? ??
5.什么是關(guān)聯(lián)查詢,有哪些?? ? ?
6.寫爬蟲(chóng)是用多進(jìn)程好?還是多線程好? 為什么?? ? ? ?
7.數(shù)據(jù)庫(kù)的優(yōu)化??
8.常見(jiàn)的反爬蟲(chóng)和應(yīng)對(duì)方法?? ? ?
9.分布式爬蟲(chóng)主要解決什么問(wèn)題?? ? ?
10.爬蟲(chóng)過(guò)程中驗(yàn)證碼怎么處理?? ? ? ?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
請(qǐng)說(shuō)一下你對(duì)迭代器和生成器的區(qū)別?
?答:(1)迭代器是一個(gè)更抽象的概念,任何對(duì)象,如果它的類有next方法和iter方法返回自己本身。對(duì)于string、list、dict、tuple等這類容器對(duì)象,使用for循環(huán)遍歷是很方便的。在后臺(tái)for語(yǔ)句對(duì)容器對(duì)象調(diào)用iter()函數(shù),iter()是python的內(nèi)置函數(shù)。iter()會(huì)返回一個(gè)定義了next()方法的迭代器對(duì)象,它在容器中逐個(gè)訪問(wèn)容器內(nèi)元素,next()也是python的內(nèi)置函數(shù)。在沒(méi)有后續(xù)元素時(shí),next()會(huì)拋出一個(gè)StopIteration異常
(2)生成器(Generator)是創(chuàng)建迭代器的簡(jiǎn)單而強(qiáng)大的工具。它們寫起來(lái)就像是正規(guī)的函數(shù),只是在需要返回?cái)?shù)據(jù)的時(shí)候使用yield語(yǔ)句。每次next()被調(diào)用時(shí),生成器會(huì)返回它脫離的位置(它記憶語(yǔ)句最后一次執(zhí)行的位置和所有的數(shù)據(jù)值)
區(qū)別:生成器能做到迭代器能做的所有事,而且因?yàn)樽詣?dòng)創(chuàng)建了__iter__()和next()方法,生成器顯得特別簡(jiǎn)潔,而且生成器也是高效的,使用生成器表達(dá)式取代列表解析可以同時(shí)節(jié)省內(nèi)存。除了創(chuàng)建和保存程序狀態(tài)的自動(dòng)方法,當(dāng)發(fā)生器終結(jié)時(shí),還會(huì)自動(dòng)拋出StopIteration異常
什么是線程安全?
線程安全是在多線程的環(huán)境下,能夠保證多個(gè)線程同時(shí)執(zhí)行時(shí)程序依舊運(yùn)行正確, 而且要保證對(duì)于共享的數(shù)據(jù)可以由多個(gè)線程存取,但是同一時(shí)刻只能有一個(gè)線程進(jìn)行存取。多線程環(huán)境下解決資源競(jìng)爭(zhēng)問(wèn)題的辦法是加鎖來(lái)保證存取操作的唯一性。
你所遵循的代碼規(guī)范是什么?請(qǐng)舉例說(shuō)明其要求?
PEP8
1變量
常量:大寫加下劃線 USER_CONSTANT
私有變量?: 小寫和一個(gè)前導(dǎo)下劃線 _private_value
Python 中不存在私有變量一說(shuō),若是遇到需要保護(hù)的變量,使用小寫和一個(gè)前導(dǎo)下劃線。但這只是程序員之間的一個(gè)約定,用于警告說(shuō)明這是一個(gè)私有變量,外部類不要去訪問(wèn)它。但實(shí)際上,外部類還是可以訪問(wèn)到這個(gè)變量。
內(nèi)置變量?: 小寫,兩個(gè)前導(dǎo)下劃線和兩個(gè)后置下劃線 __class__
兩個(gè)前導(dǎo)下劃線會(huì)導(dǎo)致變量在解釋期間被更名。這是為了避免內(nèi)置變量和其他變量產(chǎn)生沖突。用戶定義的變量要嚴(yán)格避免這種風(fēng)格。以免導(dǎo)致混亂。
2?函數(shù)和方法
總體而言應(yīng)該使用,小寫和下劃線。但有些比較老的庫(kù)使用的是混合大小寫,即首單詞小寫,之后每個(gè)單詞第一個(gè)字母大寫,其余小寫。但現(xiàn)在,小寫和下劃線已成為規(guī)范。
私有方法?:小寫和一個(gè)前導(dǎo)下劃線
?
這里和私有變量一樣,并不是真正的私有訪問(wèn)權(quán)限。同時(shí)也應(yīng)該注意一般函數(shù)不要使用兩個(gè)前導(dǎo)下劃線(當(dāng)遇到兩個(gè)前導(dǎo)下劃線時(shí),Python 的名稱改編特性將發(fā)揮作用)。
特殊方法?:小寫和兩個(gè)前導(dǎo)下劃線,兩個(gè)后置下劃線
這種風(fēng)格只應(yīng)用于特殊函數(shù),比如操作符重載等。
函數(shù)參數(shù)?: 小寫和下劃線,缺省值等號(hào)兩邊無(wú)空格
3 類
類總是使用駝峰格式命名,即所有單詞首字母大寫其余字母小寫。類名應(yīng)該簡(jiǎn)明,精確,并足以從中理解類所完成的工作。常見(jiàn)的一個(gè)方法是使用表示其類型或者特性的后綴,例如:
SQLEngine,MimeTypes對(duì)于基類而言,可以使用一個(gè) Base 或者 Abstract 前綴BaseCookie,AbstractGroup
4 模塊和包
除特殊模塊 __init__ 之外,模塊名稱都使用不帶下劃線的小寫字母。
若是它們實(shí)現(xiàn)一個(gè)協(xié)議,那么通常使用lib為后綴,例如:
import smtplib
import?os
import?sys
5?關(guān)于參數(shù)
5.1 不要用斷言來(lái)實(shí)現(xiàn)靜態(tài)類型檢測(cè)。斷言可以用于檢查參數(shù),但不應(yīng)僅僅是進(jìn)行靜態(tài)類型檢測(cè)。 Python 是動(dòng)態(tài)類型語(yǔ)言,靜態(tài)類型檢測(cè)違背了其設(shè)計(jì)思想。斷言應(yīng)該用于避免函數(shù)不被毫無(wú)意義的調(diào)用。
5.2 不要濫用 *args 和 **kwargs。*args 和 **kwargs 參數(shù)可能會(huì)破壞函數(shù)的健壯性。它們使簽名變得模糊,而且代碼常常開(kāi)始在不應(yīng)該的地方構(gòu)建小的參數(shù)解析器。
6 其他
6.1 使用 has 或 is 前綴命名布爾元素
is_connect?=?True
???????? has_member?=?False
6.2 用復(fù)數(shù)形式命名序列
members?=?['user_1',?'user_2']
6.3 用顯式名稱命名字典
person_address?=?{'user_1':'10?road?WD',?'user_2'?:?'20?street?huafu'}
6.4 避免通用名稱
諸如 list, dict, sequence 或者 element 這樣的名稱應(yīng)該避免。
6.5 避免現(xiàn)有名稱
諸如 os, sys 這種系統(tǒng)已經(jīng)存在的名稱應(yīng)該避免。
7 一些數(shù)字
一行列數(shù) : PEP 8 規(guī)定為?79 列。根據(jù)自己的情況,比如不要超過(guò)滿屏?xí)r編輯器的顯示列數(shù)。
一個(gè)函數(shù) : 不要超過(guò)?30 行代碼, 即可顯示在一個(gè)屏幕類,可以不使用垂直游標(biāo)即可看到整個(gè)函數(shù)。
一個(gè)類 : 不要超過(guò)?200 行代碼,不要有超過(guò)?10 個(gè)方法。一個(gè)模塊 不要超過(guò)?500 行。
8 驗(yàn)證腳本
可以安裝一個(gè) pep8 腳本用于驗(yàn)證你的代碼風(fēng)格是否符合 PEP8。
Python中怎么簡(jiǎn)單的實(shí)現(xiàn)列表去重?
Set
python 中 yield 的用法?
答: yield簡(jiǎn)單說(shuō)來(lái)就是一個(gè)生成器,這樣函數(shù)它記住上次返 回時(shí)在函數(shù)體中的位置。對(duì)生成器第 二次(或n 次)調(diào)用跳轉(zhuǎn)至該函 次)調(diào)用跳轉(zhuǎn)至該函 數(shù)。
什么是面向?qū)ο缶幊?#xff1f;
面向?qū)ο缶幊淌且环N解決軟件復(fù)用的設(shè)計(jì)和編程方法。 這種方法把軟件系統(tǒng)中相近相似的操作邏輯和操作 應(yīng)用數(shù)據(jù)、狀態(tài),以類的型式描述出來(lái),以對(duì)象實(shí)例的形式在軟件系統(tǒng)中復(fù)用,以達(dá)到提高軟件開(kāi)發(fā)效率的作用。
python2和python3的區(qū)別?
1.性能?
Py3.0運(yùn)行 pystone benchmark的速度比Py2.5慢30%。Guido認(rèn)為Py3.0有極大的優(yōu)化空間,在字符串和整形操作上可
以取得很好的優(yōu)化結(jié)果。?
Py3.1性能比Py2.5慢15%,還有很大的提升空間。?
2.編碼?
Py3.X源碼文件默認(rèn)使用utf-8編碼
3. 語(yǔ)法?
1)去除了<>,全部改用!=?
2)去除``,全部改用repr()?
3)關(guān)鍵詞加入as 和with,還有True,False,None?
4)整型除法返回浮點(diǎn)數(shù),要得到整型結(jié)果,請(qǐng)使用//?
5)加入nonlocal語(yǔ)句。使用noclocal x可以直接指派外圍(非全局)變量?
6)去除print語(yǔ)句,加入print()函數(shù)實(shí)現(xiàn)相同的功能。同樣的還有 exec語(yǔ)句,已經(jīng)改為exec()函數(shù)?
7)改變了順序操作符的行為,例如x<y,當(dāng)x和y類型不匹配時(shí)拋出TypeError而不是返回隨即的 bool值??
8)輸入函數(shù)改變了,刪除了raw_input,用input代替:?
?? 2.X:guess = int(raw_input('Enter an integer : ')) # 讀取鍵盤輸入的方法?
?? 3.X:guess = int(input('Enter an integer : '))
9)去除元組參數(shù)解包。不能def(a, (b, c)):pass這樣定義函數(shù)了?
10)新式的8進(jìn)制字變量,相應(yīng)地修改了oct()函數(shù)。?
11)增加了 2進(jìn)制字面量和bin()函數(shù)?
12)擴(kuò)展的可迭代解包。在Py3.X 里,a, b, *rest = seq和 *rest, a = seq都是合法的,只要求兩點(diǎn):rest是list?
對(duì)象和seq是可迭代的。?
13)新的super(),可以不再給super()傳參數(shù),?
14)新的metaclass語(yǔ)法:?
??? class Foo(*bases, **kwds):?
????? pass?
15)支持class decorator。用法與函數(shù)decorator一樣:?
4. 字符串和字節(jié)串?
1)現(xiàn)在字符串只有str一種類型,但它跟2.x版本的unicode幾乎一樣。
2)關(guān)于字節(jié)串,請(qǐng)參閱“數(shù)據(jù)類型”的第2條目?
5.數(shù)據(jù)類型?
1)Py3.X去除了long類型,現(xiàn)在只有一種整型——int,但它的行為就像2.X版本的long?
2)新增了bytes類型,對(duì)應(yīng)于2.X版本的八位串,定義一個(gè)bytes字面量的方法如下:?
???str對(duì)象和bytes對(duì)象可以使用.encode() (str -> bytes) or .decode() (bytes -> str)方法相互轉(zhuǎn)化。
?3)dict的.keys()、.items 和.values()方法返回迭代器,而之前的iterkeys()等函數(shù)都被廢棄。同時(shí)去掉的還有?
dict.has_key(),用 in替代它吧?
6.面向?qū)ο?
1)引入抽象基類(Abstraact Base Classes,ABCs)。?
2)容器類和迭代器類被ABCs化。
3)迭代器的next()方法改名為_(kāi)_next__(),并增加內(nèi)置函數(shù)next(),用以調(diào)用迭代器的__next__()方法?
4)增加了@abstractmethod和 @abstractproperty兩個(gè) decorator,編寫抽象方法(屬性)更加方便。?
7.異常?
1)所以異常都從 BaseException繼承,并刪除了StardardError?
2)去除了異常類的序列行為和.message屬性?
3)用 raise Exception(args)代替 raise Exception, args語(yǔ)法?
4)捕獲異常的語(yǔ)法改變,引入了as關(guān)鍵字來(lái)標(biāo)識(shí)異常實(shí)例?
5)異常鏈,因?yàn)開(kāi)_context__在3.0a1版本中沒(méi)有實(shí)現(xiàn)?
8.模塊變動(dòng)?
1)移除了cPickle模塊,可以使用pickle模塊代替。最終我們將會(huì)有一個(gè)透明高效的模塊。?
2)移除了imageop模塊?
3)移除了 audiodev, Bastion, bsddb185, exceptions, linuxaudiodev, md5, MimeWriter, mimify, popen2,??
rexec, sets, sha, stringold, strop, sunaudiodev, timing和xmllib模塊?
4)移除了bsddb模塊(單獨(dú)發(fā)布,可以從http://www.jcea.es/programacion/pybsddb.htm獲取)?
5)移除了new模塊?
6)os.tmpnam()和os.tmpfile()函數(shù)被移動(dòng)到tmpfile模塊下?
7)tokenize模塊現(xiàn)在使用bytes工作。主要的入口點(diǎn)不再是generate_tokens,而是 tokenize.tokenize()?
9.其它?
1)xrange() 改名為range(),要想使用range()獲得一個(gè)list,必須顯式調(diào)用:?
??? >>> list(range(10))?[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]?
2)bytes對(duì)象不能hash,也不支持 b.lower()、b.strip()和b.split()方法,但對(duì)于后兩者可以使用 b.strip(b’??\n\t\r \f’)和b.split(b’ ‘)來(lái)達(dá)到相同目的?
3)zip()、map()和filter()都返回迭代器。而apply()、 callable()、coerce()、 execfile()、reduce()和reload?()函數(shù)都被去除了現(xiàn)在可以使用hasattr()來(lái)替換 callable(). hasattr()的語(yǔ)法如:hasattr(string, '__name__')
4)string.letters和相關(guān)的.lowercase和.uppercase被去除,請(qǐng)改用string.ascii_letters 等?
5)如果x < y的不能比較,拋出TypeError異常。2.x版本是返回偽隨機(jī)布爾值的?
6)__getslice__系列成員被廢棄。a[i:j]根據(jù)上下文轉(zhuǎn)換為a.__getitem__(slice(I, j))或 __setitem__和?__delitem__調(diào)用?
7)file類被廢棄
談?wù)勀銓?duì)GIL鎖對(duì)python多線程的影響?
GIL的全稱是Global Interpreter Lock(全局解釋器鎖),來(lái)源是python設(shè)計(jì)之初的考慮,為了數(shù)據(jù)安全所做的決定。每個(gè)CPU在同一時(shí)間只能執(zhí)行一個(gè)線程(在單核CPU下的多線程其實(shí)都只是并發(fā),不是并行,并發(fā)和并行從宏觀上來(lái)講都是同時(shí)處理多路請(qǐng)求的概念。但并發(fā)和并行又有區(qū)別,并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔內(nèi)發(fā)生。)
在Python多線程下,每個(gè)線程的執(zhí)行方式:
1、獲取GIL
2、執(zhí)行代碼直到sleep或者是python虛擬機(jī)將其掛起。
3、釋放GIL???????
可見(jiàn),某個(gè)線程想要執(zhí)行,必須先拿到GIL,我們可以把GIL看作是“通行證”,并且在一個(gè)python進(jìn)程中,GIL只有一個(gè)。拿不到通行證的線程,就不允許進(jìn)入CPU執(zhí)行。
在Python2.x里,GIL的釋放邏輯是當(dāng)前線程遇見(jiàn)IO操作或者ticks計(jì)數(shù)達(dá)到100(ticks可以看作是Python自身的一個(gè)計(jì)數(shù)器,專門做用于GIL,每次釋放后歸零,這個(gè)計(jì)數(shù)可以通過(guò) sys.setcheckinterval 來(lái)調(diào)整),進(jìn)行釋放。而每次釋放GIL鎖,線程進(jìn)行鎖競(jìng)爭(zhēng)、切換線程,會(huì)消耗資源。并且由于GIL鎖存在,python里一個(gè)進(jìn)程永遠(yuǎn)只能同時(shí)執(zhí)行一個(gè)線程(拿到GIL的線程才能執(zhí)行)。
?IO密集型代碼(文件處理、網(wǎng)絡(luò)爬蟲(chóng)等),多線程能夠有效提升效率(單線程下有IO操作會(huì)進(jìn)行IO等待,造成不必要的時(shí)間浪費(fèi),而開(kāi)啟多線程能在線程A等待時(shí),自動(dòng)切換到線程B,可以不浪費(fèi)CPU的資源,從而能提升程序執(zhí)行效率),所以多線程對(duì)IO密集型代碼比較友好。
python是如何進(jìn)行內(nèi)存管理的?
一、垃圾回收:python不像C++,Java等語(yǔ)言一樣,他們可以不用事先聲明變量類型而直接對(duì)變量進(jìn)行賦值。對(duì)Python語(yǔ)言來(lái)講,對(duì)象的類型和內(nèi)存都是在運(yùn)行時(shí)確定的。這也是為什么我們稱Python語(yǔ)言為動(dòng)態(tài)類型的原因(這里我們把動(dòng)態(tài)類型可以簡(jiǎn)單的歸結(jié)為對(duì)變量?jī)?nèi)存地址的分配是在運(yùn)行時(shí)自動(dòng)判斷變量類型并對(duì)變量進(jìn)行賦值)。
二、引用計(jì)數(shù):Python采用了類似Windows內(nèi)核對(duì)象一樣的方式來(lái)對(duì)內(nèi)存進(jìn)行管理。每一個(gè)對(duì)象,都維護(hù)這一個(gè)對(duì)指向該對(duì)對(duì)象的引用的計(jì)數(shù)。當(dāng)變量被綁定在一個(gè)對(duì)象上的時(shí)候,該變量的引用計(jì)數(shù)就是1,(還有另外一些情況也會(huì)導(dǎo)致變量引用計(jì)數(shù)的增加),系統(tǒng)會(huì)自動(dòng)維護(hù)這些標(biāo)簽,并定時(shí)掃描,當(dāng)某標(biāo)簽的引用計(jì)數(shù)變?yōu)?的時(shí)候,該對(duì)就會(huì)被回收。
三、內(nèi)存池機(jī)制Python的內(nèi)存機(jī)制以金字塔行,-1,-2層主要有操作系統(tǒng)進(jìn)行操作,
第0層是C中的malloc,free等內(nèi)存分配和釋放函數(shù)進(jìn)行操作;
第1層和第2層是內(nèi)存池,有Python的接口函數(shù)PyMem_Malloc函數(shù)實(shí)現(xiàn),當(dāng)對(duì)象小于256K時(shí)有該層直接分配內(nèi)存;
第3層是最上層,也就是我們對(duì)Python對(duì)象的直接操作;
在 C 中如果頻繁的調(diào)用 malloc 與 free 時(shí),是會(huì)產(chǎn)生性能問(wèn)題的.再加上頻繁的分配與釋放小塊的內(nèi)存會(huì)產(chǎn)生內(nèi)存碎片. Python 在這里主要干的工作有:
如果請(qǐng)求分配的內(nèi)存在1~256字節(jié)之間就使用自己的內(nèi)存管理系統(tǒng),否則直接使用 malloc.
這里還是會(huì)調(diào)用 malloc 分配內(nèi)存,但每次會(huì)分配一塊大小為256k的大塊內(nèi)存.
經(jīng)由內(nèi)存池登記的內(nèi)存到最后還是會(huì)回收到內(nèi)存池,并不會(huì)調(diào)用 C 的 free 釋放掉.以便下次使用.對(duì)于簡(jiǎn)單的Python對(duì)象,例如數(shù)值、字符串,元組(tuple不允許被更改)采用的是復(fù)制的方式(深拷貝?),也就是說(shuō)當(dāng)將另一個(gè)變量B賦值給變量A時(shí),雖然A和B的內(nèi)存空間仍然相同,但當(dāng)A的值發(fā)生變化時(shí),會(huì)重新給A分配空間,A和B的地址變得不再相同
Linux基礎(chǔ)和數(shù)據(jù)結(jié)構(gòu)與算法
1. 10個(gè)常用的Linux命令?
答案:略
2. find和grep的區(qū)別?
grep命令是一種強(qiáng)大的文本搜索工具,grep搜索內(nèi)容串可以是正則表達(dá)式,允許對(duì)文本文件進(jìn)行模式查找。如果找到匹配模式, grep打印包含模式的所有行。
find通常用來(lái)在特定的目錄下搜索符合條件的文件,也可以用來(lái)搜索特定用戶屬主的文件。
3. 什么是阻塞?什么是非阻塞?
阻塞調(diào)用是指調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起。函數(shù)只有在得到結(jié)果之后才會(huì)返回。有人也許會(huì)把阻塞調(diào)用和同步調(diào)用等同起來(lái),實(shí)際上他是不同的。對(duì)于同步調(diào)用來(lái)說(shuō),很多時(shí)候當(dāng)前線程還是激活的,只是從邏輯上當(dāng)前函數(shù)沒(méi)有返回而已。例如,我們?cè)贑Socket中調(diào)用Receive函數(shù),如果緩沖區(qū)中沒(méi)有數(shù)據(jù),這個(gè)函數(shù)就會(huì)一直等待,直到有數(shù)據(jù)才返回。而此時(shí),當(dāng)前線程還會(huì)繼續(xù)處理各種各樣的消息。如果主窗口和調(diào)用函數(shù)在同一個(gè)線程中,除非你在特殊的界面操作函數(shù)中調(diào)用,其實(shí)主界面還是應(yīng)該可以刷新。socket接收數(shù)據(jù)的另外一個(gè)函數(shù)recv則是一個(gè)阻塞調(diào)用的例子。當(dāng)socket工作在阻塞模式的時(shí)候,如果沒(méi)有數(shù)據(jù)的情況下調(diào)用該函數(shù),則當(dāng)前線程就會(huì)被掛起,直到有數(shù)據(jù)為止。
非阻塞和阻塞的概念相對(duì)應(yīng),指在不能立刻得到結(jié)果之前,該函數(shù)不會(huì)阻塞當(dāng)前線程,而會(huì)立刻返回。
4. 描述數(shù)組、鏈表、隊(duì)列、堆棧的區(qū)別?
數(shù)組與鏈表是數(shù)據(jù)存儲(chǔ)方式的概念,數(shù)組在連續(xù)的空間中存儲(chǔ)數(shù)據(jù),而鏈表可以在非連續(xù)的空間中存儲(chǔ)數(shù)據(jù);
隊(duì)列和堆棧是描述數(shù)據(jù)存取方式的概念,隊(duì)列是先進(jìn)先出,而堆棧是后進(jìn)先出;隊(duì)列和堆棧可以用數(shù)組來(lái)實(shí)現(xiàn),也可以用鏈表實(shí)現(xiàn)。
5. 你知道幾種排序,講一講你最熟悉的一種?
Web框架
1.django 中當(dāng)一個(gè)用戶登錄 A 應(yīng)用服務(wù)器(進(jìn)入登錄狀態(tài)),然后下次請(qǐng)求被 nginx 代理到 B 應(yīng)用服務(wù)器會(huì)出現(xiàn)什么影響?
如果用戶在A應(yīng)用服務(wù)器登陸的session數(shù)據(jù)沒(méi)有共享到B應(yīng)用服務(wù)器,納米之前的登錄狀態(tài)就沒(méi)有了。
2.跨域請(qǐng)求問(wèn)題django怎么解決的(原理)
啟用中間件
post請(qǐng)求
驗(yàn)證碼
表單中添加{%csrf_token%}標(biāo)簽
3.請(qǐng)解釋或描述一下Django的架構(gòu)
對(duì)于Django框架遵循MVC設(shè)計(jì),并且有一個(gè)專有名詞:MVT
M全拼為Model,與MVC中的M功能相同,負(fù)責(zé)數(shù)據(jù)處理,內(nèi)嵌了ORM框架
V全拼為View,與MVC中的C功能相同,接收HttpRequest,業(yè)務(wù)處理,返回HttpResponse
T全拼為Template,與MVC中的V功能相同,負(fù)責(zé)封裝構(gòu)造要返回的html,內(nèi)嵌了模板引擎
4.django對(duì)數(shù)據(jù)查詢結(jié)果排序怎么做,降序怎么做,查詢大于某個(gè)字段怎么做
排序使用order_by()
降序需要在排序字段名前加-
查詢字段大于某個(gè)值:使用filter(字段名_gt=值)
5.說(shuō)一下Django,MIDDLEWARES中間件的作用?
答:中間件是介于request與response處理之間的一道處理過(guò)程,相對(duì)比較輕量級(jí),并且在全局上改變django的輸入與輸出。
?
6.你對(duì)Django的認(rèn)識(shí)?
Django是走大而全的方向,它最出名的是其全自動(dòng)化的管理后臺(tái):只需要使用起ORM,做簡(jiǎn)單的對(duì)象定義,它就能自動(dòng)生成數(shù)據(jù)庫(kù)結(jié)構(gòu)、以及全功能的管理后臺(tái)。
Django內(nèi)置的ORM跟框架內(nèi)的其他模塊耦合程度高。
?
應(yīng)用程序必須使用Django內(nèi)置的ORM,否則就不能享受到框架內(nèi)提供的種種基于其ORM的便利;理論上可以切換掉其ORM模塊,但這就相當(dāng)于要把裝修完畢的房子拆除重新裝修,倒不如一開(kāi)始就去毛胚房做全新的裝修。
Django的賣點(diǎn)是超高的開(kāi)發(fā)效率,其性能擴(kuò)展有限;采用Django的項(xiàng)目,在流量達(dá)到一定規(guī)模后,都需要對(duì)其進(jìn)行重構(gòu),才能滿足性能的要求。
Django適用的是中小型的網(wǎng)站,或者是作為大型網(wǎng)站快速實(shí)現(xiàn)產(chǎn)品雛形的工具。
Django模板的設(shè)計(jì)哲學(xué)是徹底的將代碼、樣式分離; Django從根本上杜絕在模板中進(jìn)行編碼、處理數(shù)據(jù)的可能。
7. Django重定向你是如何實(shí)現(xiàn)的?用的什么狀態(tài)碼?
使用HttpResponseRedirect
redirect和reverse
狀態(tài)碼:302,301
8.ngnix的正向代理與反向代理?
答:正向代理 是一個(gè)位于客戶端和原始服務(wù)器(origin server)之間的服務(wù)器,為了從原始服務(wù)器取得內(nèi)容,客戶端向代理發(fā)送一個(gè)請(qǐng)求并指定目標(biāo)(原始服務(wù)器),然后代理向原始服務(wù)器轉(zhuǎn)交請(qǐng)求并將獲得的內(nèi)容返回給客戶端。客戶端必須要進(jìn)行一些特別的設(shè)置才能使用正向代理。
反向代理正好相反,對(duì)于客戶端而言它就像是原始服務(wù)器,并且客戶端不需要進(jìn)行任何特別的設(shè)置。客戶端向反向代理的命名空間中的內(nèi)容發(fā)送普通請(qǐng)求,接著反向代理將判斷向何處(原始服務(wù)器)轉(zhuǎn)交請(qǐng)求,并將獲得的內(nèi)容返回給客戶端,就像這些內(nèi)容原本就是它自己的一樣。
9. Tornado 的核是什么?
Tornado 的核心是 ioloop 和 iostream 這兩個(gè)模塊,前者提供了一個(gè)高效的 I/O 事件循環(huán),后者則封裝了 一個(gè)無(wú)阻塞的 socket 。通過(guò)向 ioloop 中添加網(wǎng)絡(luò) I/O 事件,利用無(wú)阻塞的 socket ,再搭配相應(yīng)的回調(diào) 函數(shù),便可達(dá)到夢(mèng)寐以求的高效異步執(zhí)行。
10.Django 本身提供了 runserver,為什么不能用來(lái)部署?
runserver 方法是調(diào)試 Django 時(shí)經(jīng)常用到的運(yùn)行方式,它使用 Django 自帶的
WSGI Server 運(yùn)行,主要在測(cè)試和開(kāi)發(fā)中使用,并且 runserver 開(kāi)啟的方式也是單進(jìn)程 。
?uWSGI 是一個(gè) Web 服務(wù)器,它實(shí)現(xiàn)了 WSGI 協(xié)議、uwsgi、http 等協(xié)議。注意 uwsgi 是一種通信協(xié)議,而 uWSGI 是實(shí)現(xiàn) uwsgi 協(xié)議和 WSGI 協(xié)議的 Web 服務(wù)器。uWSGI 具有超快的性能、低內(nèi)存占用和多 app 管理等優(yōu)點(diǎn),并且搭配著 Nginx
就是一個(gè)生產(chǎn)環(huán)境了,能夠?qū)⒂脩粼L問(wèn)請(qǐng)求與應(yīng)用 app 隔離開(kāi),實(shí)現(xiàn)真正的部署 。相比來(lái)講,支持的并發(fā)量更高,方便管理多進(jìn)程,發(fā)揮多核的優(yōu)勢(shì),提升性能。
?
網(wǎng)絡(luò)編程和前端
1.AJAX是什么,如何使用AJAX?
ajax(異步的javascript 和xml) 能夠刷新局部網(wǎng)頁(yè)數(shù)據(jù)而不是重新加載整個(gè)網(wǎng)頁(yè)。
第一步,創(chuàng)建xmlhttprequest對(duì)象,var xmlhttp =new XMLHttpRequest();XMLHttpRequest對(duì)象用來(lái)和服務(wù)器交換數(shù)據(jù)。
第二步,使用xmlhttprequest對(duì)象的open()和send()方法發(fā)送資源請(qǐng)求給服務(wù)器。
第三步,使用xmlhttprequest對(duì)象的responseText或responseXML屬性獲得服務(wù)器的響應(yīng)。
第四步,onreadystatechange函數(shù),當(dāng)發(fā)送請(qǐng)求到服務(wù)器,我們想要服務(wù)器響應(yīng)執(zhí)行一些功能就需要使用onreadystatechange函數(shù),每次xmlhttprequest對(duì)象的readyState發(fā)生改變都會(huì)觸發(fā)onreadystatechange函數(shù)。
2. 常見(jiàn)的HTTP狀態(tài)碼有哪些?
200 OK
301 Moved Permanently
302 Found
304 Not Modified
307 Temporary Redirect
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
410 Gone
500 Internal Server Error
501 Not Implemented
3. Post和get區(qū)別?
1、GET請(qǐng)求,請(qǐng)求的數(shù)據(jù)會(huì)附加在URL之后,以?分割URL和傳輸數(shù)據(jù),多個(gè)參數(shù)用&連接。URL的編碼格式采用的是ASCII編碼,而不是uniclde,即是說(shuō)所有的非ASCII字符都要編碼之后再傳輸。
POST請(qǐng)求:POST請(qǐng)求會(huì)把請(qǐng)求的數(shù)據(jù)放置在HTTP請(qǐng)求包的包體中。上面的item=bandsaw就是實(shí)際的傳輸數(shù)據(jù)。
因此,GET請(qǐng)求的數(shù)據(jù)會(huì)暴露在地址欄中,而POST請(qǐng)求則不會(huì)。
2、傳輸數(shù)據(jù)的大小
在HTTP規(guī)范中,沒(méi)有對(duì)URL的長(zhǎng)度和傳輸?shù)臄?shù)據(jù)大小進(jìn)行限制。但是在實(shí)際開(kāi)發(fā)過(guò)程中,對(duì)于GET,特定的瀏覽器和服務(wù)器對(duì)URL的長(zhǎng)度有限制。因此,在使用GET請(qǐng)求時(shí),傳輸數(shù)據(jù)會(huì)受到URL長(zhǎng)度的限制。
對(duì)于POST,由于不是URL傳值,理論上是不會(huì)受限制的,但是實(shí)際上各個(gè)服務(wù)器會(huì)規(guī)定對(duì)POST提交數(shù)據(jù)大小進(jìn)行限制,Apache、IIS都有各自的配置。
3、安全性
POST的安全性比GET的高。這里的安全是指真正的安全,而不同于上面GET提到的安全方法中的安全,上面提到的安全僅僅是不修改服務(wù)器的數(shù)據(jù)。比如,在進(jìn)行登錄操作,通過(guò)GET請(qǐng)求,用戶名和密碼都會(huì)暴露再URL上,因?yàn)榈卿涰?yè)面有可能被瀏覽器緩存以及其他人查看瀏覽器的歷史記錄的原因,此時(shí)的用戶名和密碼就很容易被他人拿到了。除此之外,GET請(qǐng)求提交的數(shù)據(jù)還可能會(huì)造成Cross-site request frogery攻擊。
4.cookie 和session 的區(qū)別?
1、cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。
2、cookie不是很安全,別人可以分析存放在本地的COOKIE并進(jìn)行COOKIE欺騙考慮到安全應(yīng)當(dāng)使用session。
3、session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上。當(dāng)訪問(wèn)增多,會(huì)比較占用服務(wù)器的性能考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用COOKIE。
4、單個(gè)cookie保存的數(shù)據(jù)不能超過(guò)4K,很多瀏覽器都限制一個(gè)站點(diǎn)最多保存20個(gè)cookie。
5、建議:
?? 將登陸信息等重要信息存放為SESSION
?? 其他信息如果需要保留,可以放在COOKIE中
?
5.創(chuàng)建一個(gè)簡(jiǎn)單tcp服務(wù)器需要的流程
1.socket創(chuàng)建一個(gè)套接字
2.bind綁定ip和port
3.listen使套接字變?yōu)榭梢员粍?dòng)鏈接
4.accept等待客戶端的鏈接
5.recv/send接收發(fā)送數(shù)據(jù)
6.請(qǐng)簡(jiǎn)單說(shuō)一下三次握手和四次揮手?什么是2msl?為什么要這樣做?
2MSL即兩倍的MSL,TCP的TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài),
?
當(dāng)TCP的一端發(fā)起主動(dòng)關(guān)閉,在發(fā)出最后一個(gè)ACK包后,
即第3次握 手完成后發(fā)送了第四次握手的ACK包后就進(jìn)入了TIME_WAIT狀態(tài),
必須在此狀態(tài)上停留兩倍的MSL時(shí)間,
等待2MSL時(shí)間主要目的是怕最后一個(gè) ACK包對(duì)方?jīng)]收到,
那么對(duì)方在超時(shí)后將重發(fā)第三次握手的FIN包,
主動(dòng)關(guān)閉端接到重發(fā)的FIN包后可以再發(fā)一個(gè)ACK應(yīng)答包。
在TIME_WAIT狀態(tài) 時(shí)兩端的端口不能使用,要等到2MSL時(shí)間結(jié)束才可繼續(xù)使用。
當(dāng)連接處于2MSL等待階段時(shí)任何遲到的報(bào)文段都將被丟棄。
不過(guò)在實(shí)際應(yīng)用中可以通過(guò)設(shè)置 SO_REUSEADDR選項(xiàng)達(dá)到不必等待2MSL時(shí)間結(jié)束再使用此端口。
?
爬蟲(chóng)和數(shù)據(jù)庫(kù)
1.scrapy和scrapy-redis有什么區(qū)別?為什么選擇redis數(shù)據(jù)庫(kù)?
1) scrapy是一個(gè)Python爬蟲(chóng)框架,爬取效率極高,具有高度定制性,但是不支持分布式。而scrapy-redis一套基于redis數(shù)據(jù)庫(kù)、運(yùn)行在scrapy框架之上的組件,可以讓scrapy支持分布式策略,Slaver端共享Master端redis數(shù)據(jù)庫(kù)里的item隊(duì)列、請(qǐng)求隊(duì)列和請(qǐng)求指紋集合。
2) 為什么選擇redis數(shù)據(jù)庫(kù),因?yàn)閞edis支持主從同步,而且數(shù)據(jù)都是緩存在內(nèi)存中的,所以基于redis的分布式爬蟲(chóng),對(duì)請(qǐng)求和數(shù)據(jù)的高頻讀取效率非常高。
2. 你用過(guò)的爬蟲(chóng)框架或者模塊有哪些?談?wù)勊麄兊膮^(qū)別或者優(yōu)缺點(diǎn)?
Python自帶:urllib,urllib2
第 三 方:requests
框??? 架:Scrapy
urllib和urllib2模塊都做與請(qǐng)求URL相關(guān)的操作,但他們提供不同的功能。
urllib2.:urllib2.urlopen可以接受一個(gè)Request對(duì)象或者url,(在接受Request對(duì)象時(shí)候,并以此可以來(lái)設(shè)置一個(gè)URL 的headers),urllib.urlopen只接收一個(gè)url
urllib 有urlencode,urllib2沒(méi)有,因此總是urllib,urllib2常會(huì)一起使用的原因
scrapy是封裝起來(lái)的框架,他包含了下載器,解析器,日志及異常處理,基于多線程, twisted的方式處理,對(duì)于固定單個(gè)網(wǎng)站的爬取開(kāi)發(fā),有優(yōu)勢(shì),但是對(duì)于多網(wǎng)站爬取 100個(gè)網(wǎng)站,并發(fā)及分布式處理方面,不夠靈活,不便調(diào)整與括展。
request 是一個(gè)HTTP庫(kù), 它只是用來(lái),進(jìn)行請(qǐng)求,對(duì)于HTTP請(qǐng)求,他是一個(gè)強(qiáng)大的庫(kù),下載,解析全部自己處理,靈活性更高,高并發(fā)與分布式部署也非常靈活,對(duì)于功能可以更好實(shí)現(xiàn).
Scrapy優(yōu)缺點(diǎn):
優(yōu)點(diǎn):scrapy 是異步的
采取可讀性更強(qiáng)的xpath代替正則
強(qiáng)大的統(tǒng)計(jì)和log系統(tǒng)
同時(shí)在不同的url上爬行
支持shell方式,方便獨(dú)立調(diào)試
寫middleware,方便寫一些統(tǒng)一的過(guò)濾器
通過(guò)管道的方式存入數(shù)據(jù)庫(kù)
缺點(diǎn):基于python的爬蟲(chóng)框架,擴(kuò)展性比較差
基于twisted框架,運(yùn)行中的exception是不會(huì)干掉reactor,并且異步框架出錯(cuò)后是不會(huì)停掉其他任務(wù)的,數(shù)據(jù)出錯(cuò)后難以察覺(jué)。
3.你常用的mysql引擎有哪些?各引擎間有什么區(qū)別?
主要 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è)表來(lái)計(jì)算有多少行,但是 MyISAM 只要簡(jiǎn)單的讀出保存好的行數(shù)即
可。注意的是,當(dāng) count(*)語(yǔ)句包含 where 條件時(shí) MyISAM 也需要掃描整個(gè)表;
七、對(duì)于自增長(zhǎng)的字段,InnoDB 中必須包含只有該字段的索引,但是在 MyISAM
表中可以和其他字段一起建立聯(lián)合索引;
八、清空整個(gè)表時(shí),InnoDB 是一行一行的刪除,效率非常慢。MyISAM 則會(huì)重
建表;
九、InnoDB 支持行鎖(某些情況下還是鎖整表,如 update table set a=1 where
user like '%lee%'
4.描述下scrapy框架運(yùn)行的機(jī)制?
答:從start_urls里獲取第一批url并發(fā)送請(qǐng)求,請(qǐng)求由引擎交給調(diào)度器入請(qǐng)求隊(duì)列,獲取完畢后,調(diào)度器將請(qǐng)求隊(duì)列里的請(qǐng)求交給下載器去獲取請(qǐng)求對(duì)應(yīng)的響應(yīng)資源,并將響應(yīng)交給自己編寫的解析方法做提取處理:1. 如果提取出需要的數(shù)據(jù),則交給管道文件處理;2. 如果提取出url,則繼續(xù)執(zhí)行之前的步驟(發(fā)送url請(qǐng)求,并由引擎將請(qǐng)求交給調(diào)度器入隊(duì)列...),直到請(qǐng)求隊(duì)列里沒(méi)有請(qǐng)求,程序結(jié)束。
5.什么是關(guān)聯(lián)查詢,有哪些?
答:將多個(gè)表聯(lián)合起來(lái)進(jìn)行查詢,主要有內(nèi)連接、左連接、右連接、全連接(外連接)
6.寫爬蟲(chóng)是用多進(jìn)程好?還是多線程好? 為什么?
答:IO密集型代碼(文件處理、網(wǎng)絡(luò)爬蟲(chóng)等),多線程能夠有效提升效率(單線程下有IO操作會(huì)進(jìn)行IO等待,造成不必要的時(shí)間浪費(fèi),而開(kāi)啟多線程能在線程A等待時(shí),自動(dòng)切換到線程B,可以不浪費(fèi)CPU的資源,從而能提升程序執(zhí)行效率)。在實(shí)際的數(shù)據(jù)采集過(guò)程中,既考慮網(wǎng)速和響應(yīng)的問(wèn)題,也需要考慮自身機(jī)器的硬件情況,來(lái)設(shè)置多進(jìn)程或多線程
7.數(shù)據(jù)庫(kù)的優(yōu)化?
1. 優(yōu)化索引、SQL 語(yǔ)句、分析慢查詢;
2. 設(shè)計(jì)表的時(shí)候嚴(yán)格根據(jù)數(shù)據(jù)庫(kù)的設(shè)計(jì)范式來(lái)設(shè)計(jì)數(shù)據(jù)庫(kù);
3. 使用緩存,把經(jīng)常訪問(wèn)到的數(shù)據(jù)而且不需要經(jīng)常變化的數(shù)據(jù)放在緩存中,能
節(jié)約磁盤IO;
4. 優(yōu)化硬件;采用SSD,使用磁盤隊(duì)列技術(shù)(RAID0,RAID1,RDID5)等;
5. 采用MySQL 內(nèi)部自帶的表分區(qū)技術(shù),把數(shù)據(jù)分層不同的文件,能夠提高磁
盤的讀取效率;
6. 垂直分表;把一些不經(jīng)常讀的數(shù)據(jù)放在一張表里,節(jié)約磁盤I/O;
7. 主從分離讀寫;采用主從復(fù)制把數(shù)據(jù)庫(kù)的讀操作和寫入操作分離開(kāi)來(lái);
8. 分庫(kù)分表分機(jī)器(數(shù)據(jù)量特別大),主要的的原理就是數(shù)據(jù)路由;
9. 選擇合適的表引擎,參數(shù)上的優(yōu)化;
10. 進(jìn)行架構(gòu)級(jí)別的緩存,靜態(tài)化和分布式;
11. 不采用全文索引;
12. 采用更快的存儲(chǔ)方式,例如 NoSQL存儲(chǔ)經(jīng)常訪問(wèn)的數(shù)據(jù)
8.常見(jiàn)的反爬蟲(chóng)和應(yīng)對(duì)方法?
1).通過(guò)Headers反爬蟲(chóng)
從用戶請(qǐng)求的Headers反爬蟲(chóng)是最常見(jiàn)的反爬蟲(chóng)策略。很多網(wǎng)站都會(huì)對(duì)Headers的User-Agent進(jìn)行檢測(cè),還有一部分網(wǎng)站會(huì)對(duì)Referer進(jìn)行檢測(cè)(一些資源網(wǎng)站的防盜鏈就是檢測(cè)Referer)。如果遇到了這類反爬蟲(chóng)機(jī)制,可以直接在爬蟲(chóng)中添加Headers,將瀏覽器的User-Agent復(fù)制到爬蟲(chóng)的Headers中;或者將Referer值修改為目標(biāo)網(wǎng)站域名。對(duì)于檢測(cè)Headers的反爬蟲(chóng),在爬蟲(chóng)中修改或者添加Headers就能很好的繞過(guò)。
2).基于用戶行為反爬蟲(chóng)
還有一部分網(wǎng)站是通過(guò)檢測(cè)用戶行為,例如同一IP短時(shí)間內(nèi)多次訪問(wèn)同一頁(yè)面,或者同一賬戶短時(shí)間內(nèi)多次進(jìn)行相同操作。
大多數(shù)網(wǎng)站都是前一種情況,對(duì)于這種情況,使用IP代理就可以解決。可以專門寫一個(gè)爬蟲(chóng),爬取網(wǎng)上公開(kāi)的代理ip,檢測(cè)后全部保存起來(lái)。這樣的代理ip爬蟲(chóng)經(jīng)常會(huì)用到,最好自己準(zhǔn)備一個(gè)。有了大量代理ip后可以每請(qǐng)求幾次更換一個(gè)ip,這在requests或者urllib2中很容易做到,這樣就能很容易的繞過(guò)第一種反爬蟲(chóng)。
對(duì)于第二種情況,可以在每次請(qǐng)求后隨機(jī)間隔幾秒再進(jìn)行下一次請(qǐng)求。有些有邏輯漏洞的網(wǎng)站,可以通過(guò)請(qǐng)求幾次,退出登錄,重新登錄,繼續(xù)請(qǐng)求來(lái)繞過(guò)同一賬號(hào)短時(shí)間內(nèi)不能多次進(jìn)行相同請(qǐng)求的限制。
3).動(dòng)態(tài)頁(yè)面的反爬蟲(chóng)
上述的幾種情況大多都是出現(xiàn)在靜態(tài)頁(yè)面,還有一部分網(wǎng)站,我們需要爬取的數(shù)據(jù)是通過(guò)ajax請(qǐng)求得到,或者通過(guò)JavaScript生成的。首先用Fiddler對(duì)網(wǎng)絡(luò)請(qǐng)求進(jìn)行分析。如果能夠找到ajax請(qǐng)求,也能分析出具體的參數(shù)和響應(yīng)的具體含義,我們就能采用上面的方法,直接利用requests或者urllib2模擬ajax請(qǐng)求,對(duì)響應(yīng)的json進(jìn)行分析得到需要的數(shù)據(jù)。
能夠直接模擬ajax請(qǐng)求獲取數(shù)據(jù)固然是極好的,但是有些網(wǎng)站把a(bǔ)jax請(qǐng)求的所有參數(shù)全部加密了。我們根本沒(méi)辦法構(gòu)造自己所需要的數(shù)據(jù)的請(qǐng)求。這種情況下就用selenium+phantomJS,調(diào)用瀏覽器內(nèi)核,并利用phantomJS執(zhí)行js來(lái)模擬人為操作以及觸發(fā)頁(yè)面中的js腳本。從填寫表單到點(diǎn)擊按鈕再到滾動(dòng)頁(yè)面,全部都可以模擬,不考慮具體的請(qǐng)求和響應(yīng)過(guò)程,只是完完整整的把人瀏覽頁(yè)面獲取數(shù)據(jù)的過(guò)程模擬一遍。
用這套框架幾乎能繞過(guò)大多數(shù)的反爬蟲(chóng),因?yàn)樗皇窃趥窝b成瀏覽器來(lái)獲取數(shù)據(jù)(上述的通過(guò)添加 Headers一定程度上就是為了偽裝成瀏覽器),它本身就是瀏覽器,phantomJS就是一個(gè)沒(méi)有界面的瀏覽器,只是操控這個(gè)瀏覽器的不是人。利selenium+phantomJS能干很多事情,例如識(shí)別點(diǎn)觸式(12306)或者滑動(dòng)式的驗(yàn)證碼,對(duì)頁(yè)面表單進(jìn)行暴力破解等。
9.分布式爬蟲(chóng)主要解決什么問(wèn)題?
1)ip
2)帶寬
3)cpu
4)io
10.爬蟲(chóng)過(guò)程中驗(yàn)證碼怎么處理?
1.scrapy自帶(但是成功率不高)
2.付費(fèi)接口(若快http://www.ruokuai.com/home/pricetype)
其他
更多面試資料請(qǐng)加關(guān)注
總結(jié)
以上是生活随笔為你收集整理的【Python】模拟面试技术面试题答的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 汇编语言子程序设计 查找电话号码
- 下一篇: Python爬虫个人记录(二) 获取fi