模擬面試題總結
1,你最熟悉的Unix環境是CentOS Linux下查詢環境變數的命令是env查詢指令碼定時任務的命令是crontab -l
2,寫出在網路爬蟲爬取資料的過程中 遇到的防爬蟲問題的解決方案
針對爬蟲禁止訪問:在請求頭中使用使用者代理user-agent,偽裝成瀏覽器
使用者行為分析(併發量、線上時間):使用IP代理池,限制併發量
動態載入資料(Ajax和js):使用selenium或者換用其他平臺獲取json資料
3,使用python編寫一個簡單的爬蟲功能 並寫出分析的步驟 寫出每一步的詳細過程 注意:寫出自己的分析過程 以及每一步的詳細過程
# -*- coding:utf-8 -*-
import requests,json
from lxml import etree
from retrying import retry
class Proxy(object):
def __init__(self):
self.base_url = 'http://www.data5u.com/free/'
self.header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'}
self.proxy_pool = []
@retry(stop_max_attempt_number = 3)
def get_html(self):
response = requests.get(self.base_url,headers=self.header) if response.status_code == 200:
html = response.content
e_html = etree.HTML(html)
return e_html
def parse_html(self):
html_text = self.get_html()
proxy = {}
data_list = html_text.xpath('//ul[@class="l2"]')
for data in data_list:
ip_port= {}
proxy['ip'] = data.xpath('./span[1]/li/text()')
proxy['port'] = data.xpath('./span[2]/li/text()')
proxy['anoy'] = data.xpath('./span[3]/li/a/text()')
proxy['cate'] = data.xpath('./span[4]/li/a/text()')
proxy['country'] = data.xpath('./span[5]/li/a/text()')
proxy['area'] = data.xpath('./span[6]/li/a/text()')
proxy['isp'] = data.xpath('./span[7]/li/a/text()')
proxy['delay'] = data.xpath('./span[8]/li/text()')
proxy['update'] = data.xpath('./span[9]/li/text()')
for k,v in proxy.items():
print(k,'————',v)
if float(proxy['delay'][0].split('秒')[0].strip()) > 1.0:
ip_port['http'] = proxy['ip'][0] +':'+ proxy['port'][0]
print('————當前ip捨棄————')
self.proxy_pool.append(ip_port)
def save_file(self):
with open('5udata可用ip代理.json','w+') as f:
f.seek(0,0)
f.write('[\n')
for item in self.proxy_pool:
data = json.dumps(item) + ',\n'
f.write(data)
f.write(']')
print('資料已經儲存完畢')
def run(self):
self.get_html()
self.parse_html()
self.save_file()
def main():
proxy = Proxy()
proxy.run()
if __name__ == '__main__':
main()
分析思路:
- 定義一個Proxy類,用目的url和使用者代理初始話類
- 在類中定義一個get_html()函式,通過requests使用者向目的url傳送頁面請求,獲取指定url的頁面原始碼,返回etree類轉化的頁面物件
- 定義一個解析頁面的函式parse_html(),通過xpath獲取頁面上需要的資訊資料,並將獲取到的資料儲存在字典中,將字典放在資料佇列中
- 定義一個save_file()檔案儲存函式,從儲存字典的佇列中取出資料並按條儲存到本地檔案中
4簡要說明檢視的作用
在Django框架中檢視是:定義完成各類物件所需功能的函式,接收請求,處理業務邏輯,返回結果
在MySQL資料中檢視是:查詢語句執行後返回的結果集,是對若干張基本表的引用,一張續表,查詢語句執行的結果,不儲存資料,方便操作,增強可讀性,更加安全
5 列舉你使用過的python網路爬蟲所用到的解析資料包(最熟悉的在前)
lxml,python標準庫,html5lib
6 列舉你使用過的python中的編碼方式(最熟悉的在前)
utf-8,ANSI,gbk-2312,big5,iso-8859
7 python3.5語言中的enumerate 意思是帶序號地輸出物件中的元素
8 十進位制99的八進位制的表述方式o143
9 列舉四種常用的排序演算法
氣泡排序、選擇排序、插入排序、快速排序
10 列出比較熟悉的爬蟲框架
requests、scrapy、pyspider
11 每天早上6點到12點每隔2小時執行一次 /usr/bin/httpd.sh 怎麼實現
crontab -e
6-12/2 * * * /usr/bin/httpd.sh restart
12 os.path 和sys.path的區別
os.path:主要用於作業系統本地檔案目錄
sys.path:主要用於操作python編譯器的環境變數
13 deepcopy 和 copy的區別
deepcopy:包含物件裡面的子物件的拷貝,原始物件的改變不會造成拷貝里的任何改變
copy:淺拷貝,只拷貝頂層元素,沒有拷貝子物件,原始資料改變,拷貝後的物件也會改變
14 說明os 和sys的不同 並列舉常用的模組方法
os模組主要是用於使用者對底層系統的操作
sys主要是使用者對python直譯器的操作
兩個模組中都有path方法,在os模組中主要用於在系統建立檔案和目錄,sys模組主要用於修改python直譯器的環境引數
15 re模組中match 和search方法有什麼不同
match方法是從字串的第一個字元開始匹配,第一個字元匹配上才開始匹配後面的字元,如果不匹配就停止匹配,返回匹配到的第一段字串
search方法在字串中從前往後匹配,可以在字串中任何位置開始匹配,返回第一個匹配到的第一段字串
16 如何匹配<html><title></title></html> 得到<html>
re.match(r‘(.+?)<title>’,’<html><title></title></html>’).group(1)
17 通過重寫內建函式 實現檔案open之前檢查檔案格式
def open(filename,mode):
import __builtin__
file = __builtin__.open(filename,mode)
if file.read(5) not in("GIF87", "GIF89"):
raise IOError, "not aGIF file"
file.seek(0)
return file
fp = open("sample/test.gif","r")
print len(fp.read()), "bytes"</span>
18 設計實現遍歷目錄與子目錄 抓取.pyc 檔案
# coding:utf-8 -*-
import os
lists = []
def get_pyc(def_path=None):
global lists
if not def_path:
def_path = os.getcwd()
os.chdir(def_path)
dirs = os.listdir()
for di in dirs:
if os.path.isfile(di):
index = di.rfind('.')
postfix = di[index:]
if postfix == '.pyc':
lists.append(di)
else:
get_pyc(di)
os.chdir('../')
def main():
dirs = input('請輸入插敘路徑:')
get_pyc(dirs)
print('當前目錄中所有.pyc檔案如下:')
for li in lists:
print(li)
if __name__ == "__main__":
main()
19 簡述raid原理
磁碟陣列(Redundant Arrays of Independent Disks,RAID),有“獨立磁碟構成的具有冗餘能力的陣列”之意。
磁碟陣列作為獨立系統在主機外直連或通過網路與主機相連。磁碟陣列有多個埠可以被不同主機或不同埠連線。一個主機連線陣列的不同埠可提升傳輸速度。
和當時PC用單磁碟內部整合快取一樣,在磁碟陣列內部為加快與主機互動速度,都帶有一定量的緩衝儲存器。主機與磁碟陣列的快取互動,快取與具體的磁碟互動資料。
20 簡述weblogic 域與server之間的關係
domain是weblogic管理的基本單元,在domain中必須有一個Server,也可以有多個Server ,domain是為了劃分不同的應用或統一應用不同價階段(開發\測試\生產)而設計的,一般在生產環境下我們不原意將兩個不同的程式部署到同一個server上,因為任意一個應用出現問題,會直接影響另外一個應用,有了domain就可以將兩個不同的應用部署到兩個不同的domain中去,domain起到應用邏輯劃分的好處。
domain中可以建多個server在cluster環境下,是有多個server的,所以我們需要對這些server的資訊進行管理,所以admin server的概念也就出來了,admin server是對其他server進行管理的一個伺服器.
21 python是允許多執行緒的嗎 介紹下python 平行計算的一些方法
python允許多執行緒,多執行緒通過threading模組中Thread類來實現
並行執行一般使用的是多程序,多執行緒可以在呼叫C語言編譯的程式碼塊下也可實現平行計算
22 介紹python中的with方法
with還可以很好的處理上下文環境產生的異常,Python對with的處理還很聰明。基本思想是with所求值的物件必須有一個__enter__()方法,一個__exit__()方法。緊跟with後面的語句被求值後,返回物件的__enter__()方法被呼叫,這個方法的返回值將被賦值給as後面的變數。當with後面的程式碼塊全部被執行完之後,將呼叫前面返回物件的__exit__()方法,自動將檔案關閉退出
23 介紹下*args 和**kwargs的區別
python中的可變引數*args 表示任何多個無名引數,它是一個tuple;**kwargs 表示關鍵字引數,它是一個dict。並且同時使用*args和**kwargs時,必須*args引數列要在**kwargs前
24 介紹下@classmethod @staticmethod @property區別
@classmethod:類方法裝飾器,呼叫類中的方法裝飾目標物件
@staticmethod:靜態方法裝飾器,是跟類物件沒有多大聯絡的一個函式,被定義後可以被類物件呼叫
@property:將方法變成物件的一個屬性,可以直接訪問類物件的屬性
25 介紹下python函式引數傳遞的型別
python中函式引數傳遞為傳引用
對於不可變型別(如數值、字串、元組等),由於值不可改變,傳過去的效果類似C語言裡面的傳值
對於可變型別(如列表),值可以被修改,實現的效果類似C語言中的傳引用
26 __new__ 和 __init__的區別
__new__是在建立物件前呼叫,建立例項物件並返回例項物件
__init__在例項物件建立完成後呼叫,並對該物件初始化
27介紹python中yield的用法
yeild具有阻塞函式輸出結果,並記錄本次執行所有資料(暫存器、時間片等)的功能,在next()或__next__函式作用下逐個輸出所有資料
yield用在函式中,函式就是一個生成器,返回可迭代物件在for迴圈和next()函式配合下可以遍歷所有物件
線上程中使用yield可以實現協程
28 Django裡QuerySet的get和filter方法的區別
【輸入引數】
get 的引數只能是model中定義的那些欄位,只支援嚴格匹配
filter 的引數可以是欄位,也可以是擴充套件的where查詢關鍵字,如in,like等
【返回值】
get 返回值是一個定義的model物件
filter 返回值是一個新的QuerySet物件,然後可以對QuerySet在進行查詢返回新的QuerySet物件,支援鏈式操作QuerySet一個集合物件,可使用迭代或者遍歷,切片等,但是不等於list型別(使用一定要注意)
【異常】
get 只有一條記錄返回的時候才正常,也就說明get的查詢欄位必須是主鍵或者唯一約束的欄位。當返回多條記錄或者是沒有找到記錄的時候都會丟擲異常
filter 有沒有匹配的記錄都可以
29簡述Django對http請求的執行流程
在接受一個Http請求之前的準備
啟動一個支援WSGI閘道器協議的伺服器監聽埠等待外界的Http請求,比如Django自帶的開發者伺服器或者uWSGI伺服器。
伺服器根據WSGI協議指定相應的Handler來處理Http請求,並且初始化該Handler,在Django框架中由框架自身負責實現這一個Handler。
此時伺服器已處於監聽狀態,可以接受外界的Http請求
當一個http請求到達伺服器的時候
伺服器根據WSGI協議從Http請求中提取出必要的引數組成一個字典(environ)並傳入Handler中進行處理。
在Handler中對已經符合WSGI協議標準規定的http請求進行分析,比如載入Django提供的中介軟體,路由分配,呼叫路由匹配的檢視等。
返回一個可以被瀏覽器解析的符合Http協議的HttpResponse。
30 簡述Django下的(內建)快取機制
Django根據設定的快取方式,瀏覽器第一次請求時,cache會快取單個變數或整個網頁等內容到硬碟或者記憶體中,同時設定response頭部,當瀏覽器再次發起請求時,附帶f-Modified-Since請求時間到Django,Django 發現f-Modified-Since會先去引數之後,會與快取中的過期時間相比較,如果快取時間比較新,則會重新請求資料,並快取起來然後返回response給客戶端,如果快取沒有過期,則直接從快取中提取資料,返回給response給客戶端。
31Django中model的SlugField型別欄位有什麼用途
SlugField欄位是將輸入的內容中的空格都替換成‘-’之後儲存,Slug 是一個新聞術語,通常是某些東西的短標籤。一個slug只能包含字母、數字、下劃線或者是連字元,通常用來作為短標籤。通常它們是用來放在URL裡的。
SlugField欄位的Field.db_index自動設定為True。
通常根據另一個值自動生成slug來填充到SlugField的值
32Django中如何載入初始化資料
Django在建立物件時在盜用save()方法後,ORM框架會把物件的屬性轉換為寫入到資料庫中,實現對資料庫的初始化;通過操作物件,查詢資料庫,將查詢集返回給檢視函式,通過模板語言展現在前端頁面
33 什麼是lambda函式 他有什麼用途
lambda函式是匿名函式
匿名函式可以建立小型匿名的函式無需def宣告
可以將函式作為引數傳遞
34 python中如何進行資料型別的轉換
Python 內建的常用函式還包括資料型別轉換函式,比如 int() 函式可以
把其他資料型別轉換為整數,常用的型別轉換函式為:
int(x [,base])
將x轉換為一個整數
long(x [,base] )
將x轉換為一個長整數
float(x)
將x轉換到一個浮點數
complex(real [,imag])
建立一個複數
str(x)
將物件 x 轉換為字串
repr(x)
將物件 x 轉換為表示式字串
eval(str)
用來計算在字串中的有效Python表示式,並返回一個物件
tuple(s)
將序列 s 轉換為一個元組
list(s)
將序列 s 轉換為一個列表
set(s)
轉換為可變集合
dict(d)
建立一個字典。d 必須是一個序列 (key,value)元組。
frozenset(s)
轉換為不可變集合
chr(x)
將一個整數轉換為一個字元
unichr(x)
將一個整數轉換為Unicode字元
ord(x)
將一個字元轉換為它的整數值
hex(x)
將一個整數轉換為一個十六進位制字串
oct(x)
將一個整數轉換為一個八進位制字串
35python中類方法 類例項方法 靜態方法有和區別
在類裡面定義的函式就是方法,類方法需要@ classmethod 修飾並且有個隱藏引數 cls,例項方法必須有個引數 self, 靜態方法必須有 @staticmethod修飾
類和例項都可以訪問靜態方法,例項可以訪問例項方法也可以訪問類方法,類可以訪問類方法也可以訪問例項方法,訪問例項方法必須要帶引數 self, 可以理解為類其實也是一個例項,類訪問例項方法不帶引數會報錯的.類本身可以訪問函式,例項卻不行
36 python中pass語句的作用是什麼
pass語句什麼也不做,一般作為佔位符或者建立佔位程式,pass語句不會執行任何操作
37介紹下python中range() 和 xrange()函式的用法
range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個序列
xrange用法與range完全相同,所不同的是生成的不是一個數組,而是一個可迭代物件
range比xrange開銷要大,原因是range會直接生成一個list物件,而xrange每次呼叫返回其中的一個值
38 python匹配HTML tag的時候<.*>和<.*?>有什麼區別
<.*>會按照貪婪模式匹配,會從第一個“<”開始一直匹配到最後一個“>”,即使中間有“<”和“>”也全部匹配進去,不會停止;
<.*?>按照非貪婪模式匹配,在保證後面的表示式也能正確匹配的前提下儘量多的匹配
39 函式 類方法定義中如何實現可選引數 可選關鍵詞引數
class People(object):
#類方法,用classmethod來進行修飾
@classmethod
def getCountry(cls,*args,**kwargs):
if args:
for arg in args:
print(arg)
if kwargs:
for k,v in kwargs.items():
print(k,'是:',v)
People.getCountry('我是中國人',語言='漢語',首都='北京')
40 請寫一段程式 包含迭代器和生成器的使用
G = ( x*2 for x in range(5))
for x in G:
print (G)
41 何時使用標準庫 collections 中的deque
deque其實是 double-ended queue 的縮寫,翻譯過來就是雙端佇列,它最大的好處就是實現了從佇列 頭部快速增加和取出物件:
.popleft(),
.appendleft()
但是值得注意的是,list物件的這兩種用法的時間複雜度是 O(n) ,也就是說隨著元素數量的增加耗時呈 線性上升。而使用deque物件則是 O(1) 的複雜度,所以當你的程式碼有這樣的需求的時候, 一定要記得使用deque。
deque還可以限制佇列長度,如果長於佇列則會刪除
如果是是append則會刪除最左端的元素
如果是apppendleft則會刪除最右端的元素
collections中有幾個非常好用的資料型別
Python擁有一些內建的資料型別,比如str, int, list, tuple, dict等, collections模組在這些內建資料型別的基礎上,提供了幾個額外的資料型別:
namedtuple(): 生成可以使用名字來訪問元素內容的tuple子類
deque: 雙端佇列,可以快速的從另外一側追加和推出物件
Counter: 計數器,主要用來計數
OrderedDict: 有序字典
defaultdict: 帶有預設值的字典
42 如何使用標準庫pdb 除錯python程式
在python中使用pdb模組可以進行除錯
import pdb
pdb.set_trace()
也可以使用python -m pdb myscript.py這樣的方式
43 如何使用裝飾器
在不能改能原始碼的前提下,增加額外的功能,此時就可以使用裝飾器,裝飾器是一個實現主體是一個閉包,在原始要裝飾的函式上使用@和閉包外層函式名即可裝飾該函式,在函式的下方呼叫原函式名,即可執行
44 引數傳遞使用的是傳遞引用還是傳遞值 為什麼
python中函式引數傳遞為傳引用
對於不可變型別(如數值、字串、元組等),由於值不可改變,傳過去的效果類似C語言裡面的傳值
對於可變型別(如列表),值可以被修改,實現的效果類似C語言中的傳引用
45說明 Cpython 的記憶體管理機制
【引用計數】
每一個Python物件都有一個引用計數器----用於記錄有多少其他物件指向(引用)這個物件。它儲存在變數 refcnt 中,並通過呼叫C巨集Py_INCREF實現引用計數增加和Py_DECREF實現引用計數減少的操作。 Py_DECREF更復雜點,當引用計數器到零時,它會執行該物件的釋放函式,回收該型別的物件
迴圈引用只能由容器物件建立,因此Python GC不會跟蹤整數,字串等型別。
【垃圾回收】
GC將物件分為3代,每一代物件都有一個計數器和一個閾值。當物件被建立時,閾值會被自動地指派為0,也就是第0代物件。當計數器大於某個閥值,GC就會執行在當前物件代上,回收該物件。沒被回收的物件會被移至下一代,並且將相應的計數器復位。下一代的物件保留在下一代
46 寫一個函式實現功能:返回1到10億之間的所有的素數
# -*- coding:utf-8 -*-
import math
def print_prime()
nums = (x for x in range(1,1000000000))
lists = []
for num in nums:
i = 2
# 2太特殊,下面的演算法不能直接排除
if num == 2:
print(num)
lists.append(num)
continue
while i < math.ceil(num**0.5)+1:
if (num%i) == 0:
i += 1
break
else:
if i == math.ceil(num**0.5):
lists.append(num)
print(num)
i += 1
print(lists)
return list
if __name__ == ‘__main__’:
prime = print_prime()
print(prime)
47寫一個函式實現如下功能: 以升序的方式融合這2個列表 list1 =[2,4,5,9,20,8,7] list2 =[21,25,42,39,8] 並返回融合後的列表 要求: 不能使用python自帶的sort list.sort 函式
def mer_sort(lista,listb):
lista.extend(listb)
new_list = lista
for i in range(len(new_list),0,-1):
for y in range(i-1):
if new_list[y] < new_list[y+1]:
continue
else:
new_list[y],new_list[y+1] = new_list[y+1],new_list[y]
return new_list
list1 = [2,4,5,9,20,8,7]
list2 =[21,25,42,39,8]
result = mer_sort(list1,list2)
print(result)
48 在python中 list tuple dict set有什麼區別主要的應用場景
list列表,用一對方括號括起來,其中的元素可以是不同的資料型別,可以有重複資料,是可變型別;主要用在資料多,型別不同統一的需要修改的資料結構中
tuple元組,用一對圓括號括起來,元素可以是不同的型別,可以重複,是不可變型別;主要用在主要用在資料類多,型別不同統一的不能修改的資料結構中
dict字典用一對大括號括起來,以鍵值對的形式儲存的資料,鍵必須是字串,值可以是任何型別;主要用在需要查詢的資料結構中,提高查詢效率
set集合用一對大括號括起來,裡面的元素基本的資料(數值、字串等),不能有重複元素;可以用在對資料進行去重和篩選的資料結構中
49 關係型資料庫中表與表之間的左連線 內連線 外連線 分別解釋下他們的含義和區別
左連線:查詢結果顯示左表的所有資料和右邊連線表中滿足where條件的資料
內連線:查詢結果僅包含符合連線條件的資料,兩張表都要符合連線條件
外連線:連線結果不僅包含符合連線條件的資料還包含不符合連線條件的資料包含左外連線(左連線)、右外連線(右連線)、全外連線
50 python是怎樣進行記憶體管理的
引用計數
python內部使用引用計數,來保持追蹤記憶體中的物件,Python內部記錄了物件有多少個引用,即引用計數,當物件被建立時就建立了一個引用計數,當物件不再需要時,這個物件的引用計數為0時,它被垃圾回收。
垃圾回收
、當記憶體中有不再使用的部分時,垃圾收集器就會把他們清理掉。它會去檢查那些引用計數為0的物件,然後清除其在記憶體的空間。當然除了引用計數為0的會被清除,還有一種情況也會被垃圾收集器清掉:當兩個物件相互引用時,他們本身其他的引用已經為0了。
2、垃圾回收機制還有一個迴圈垃圾回收器, 確保釋放迴圈引用物件(a引用b, b引用a, 導致其引用計數永遠不為0)。
記憶體池
Python提供了對記憶體的垃圾收集機制,但是它將不用的記憶體放到記憶體池而不是返回給作業系統。
Python中所有小於256個位元組的物件都使用pymalloc實現的分配器,而大的物件則使用系統的 malloc。另外Python物件,如整數,浮點數和List,都有其獨立的私有記憶體池,物件間不共享他們的記憶體池。也就是說如果你分配又釋放了大量的整數,用於快取這些整數的記憶體就不能再分配給浮點數。
51 介紹下except的用法和作用
Python的except用來捕獲所有異常, 因為Python裡面的每次錯誤都會丟擲 一個異常,所以每個程式的錯誤都被當作一個執行時錯誤,except一般是結合try和finally一起使用,主要是當指定的程式碼塊出現了預設的異常後,可以捕獲該異常,並進行相應的處理,無論是否發生異常finally後面的程式碼都會執行