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