換了個地方,來北京工作,面試了4家python爬蟲,寫一些這四家(記得的)筆試題(1)
1、請簡要說明檢視的作用
資料庫檢視,隱藏資料複雜性;有利於使用者對於資料庫中某些列資料的訪問
使使用者查詢變得簡單
2、列舉您使用過的python網路爬蟲所用到的網路資料包(最熟悉的在前):
requests,urllib2,urllib
3、列舉您使用過的python網路爬蟲所用到的解析資料包(最熟悉的在前):
xpath, beautifulsoup
4、列舉您使用過的python中的編碼方式(最熟悉的在前):
utf-8,gbk
5、python3.5語言中enumerate的意思是_______________________
在python中是列表,列舉
6、99的八進位制表示是
143
7、請舉出三種常用的排序演算法
冒泡,選擇,快速
8、列出比較熟悉的爬蟲框架
scrapy
9、 用4、 9 、 2、 7四個數字,可以使用+、-、*和/,每個數字使用一次,使表示式的結果為24,表示式是_____________________________
24=(9+7-4)*2
10、您最熟悉的Unix環境是_____________.Unix下查詢環境變數的命令是________,查詢指令碼定時任務的命令是____________________
ubentu,echo $環境變數名稱;crontab -l
11、
1. 應用手機的網頁頁面;2. 設定多個
通過headers反爬蟲:解決策略,偽造headers
基於使用者行為反爬蟲:動態變化去爬取資料,模擬普通使用者的行為
基於動態頁面的反爬蟲:跟蹤伺服器傳送的ajax請求,模擬ajax請求
12、 閱讀以下Python程式
for i in range(5,0,-1):
print(i)
請在下面寫出列印結果
5,4,3,2,1
13、在某系統中一個整數佔用兩個八位位元組,使用Python按下面的要求編寫完整程式。
接收從標準輸入中依次輸入的五個數字,將其組合成為一個整數,放入全域性變數
14、 post、get有什麼區別?
1. 根據HTTP規範,GET一般用於獲取/查詢資源資訊,應該是安全的和冪等。而POST一般用於更新資源資訊2. get是在url中傳遞資料,資料放在請求頭中。 post是在請求體中傳遞資料3. get傳送的資料量較小,只能在請求頭上傳送資料。post傳送的資料量較大,一般被預設為不受限制。5. get安全性非常低,post安全性較高。但是執行效率卻比Post方法好。
建議:1、get方式的安全性較Post方式要差些,包含機密資訊的話,建議用Post資料提交方式;2、在做資料查詢時,建議用Get方式;而在做資料新增、修改或刪除時,建議用Post方式;
Get 在url中傳遞資料,資料資訊放在請求頭中;而post請求資訊放在請求體中進行傳遞資料;get傳輸資料的資料量較小,只能在請求頭中傳送資料。
Post傳輸資料資訊比較大,一般不受限制;
Get資料傳輸安全性低,post傳輸資料安全性高
在執行效率來說,get比post好
2、 http、https協議有什麼區別?
https 相對於http 來說對於網頁更安全;
http協議是超文字傳輸協議,被用於在web瀏覽器和網站伺服器之間傳遞資訊。http協議工作是以明文方式傳送內容,不提供任何形式的資料加密,而這也是很容易被黑客利用的地方,如果黑客截取了web瀏覽器和網站伺服器之間的傳輸資訊,就可以直接讀懂其中的資訊,因此http協議不適合傳輸一些重要的、敏感的資訊,比如信用卡密碼及支付驗證碼等。
安全套接字層https協議就是為了解決http協議的這一安全缺陷而出生的,為了資料傳輸的安全,https在http的基礎上加入了ssl協議,ssl依靠證書來驗證伺服器的身份,為瀏覽器和伺服器之間的通訊加密,這樣的話即使黑客借去了傳送過程中的資訊,也無法破解讀懂它,我們網站及使用者的資訊便得到了最大的安全保障。
https協議需要到ca申請證書,一般免費證書很少,需要費用。
http是超文字傳輸協議,資訊是明文傳輸,https 則是具有安全性的ssl加密傳輸協議
http和https使用的是完全不同的連線方式用的埠也不一樣,前者是80,後者是443。
http的連線很簡單,是無狀態的, HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議 要比http協議安全
http是超文字傳輸協議,資訊明文傳輸;https是http與ssl加密傳輸的
http連線的埠應用的是80;https連線的埠應用443
http連線無狀態;而https連線是應用http與ssl協議進行連線,可以進行加密傳輸與身份驗證等服務,比http更加安全
3、 域名和IP之間有什麼關係,如何檢視某個域名對應的所有IP?
國際網際網路(Internet)上有成千百萬臺主機(host),為了區分這些主機,人們給每臺主機都分配了一個專門的“地址”作為標識,稱為IP地址
由於IP地址全是些的數字,為了便於使用者記憶,Internet上引進了域名服務系統DNS(Domain Name System)。
當您鍵入某個域名的時候,這個資訊首先到達提供此域名解析的伺服器上,再將此域名解析為相應網站的IP地址。完成這一任務的過程就稱為域名解析。
1.ping 2.nslookup 3.使用站長工具等
在網際網路上有成千上萬的主機,為了區分這些主機,為每一個主機分配了IP,而IP全是數字,為了方便人們記憶,生成了域名,
Ping;站長工具
4、 http協議頭中,keep-alive欄位有什麼作用?
HTTP協議採用“請求-應答”模式,當使用普通模式,即非KeepAlive模式時,每個請求/應答客戶和伺服器都要新建一個連線,完成 之後立即斷開連線(HTTP協議為無連線的協議);
當使用Keep-Alive模式(又稱持久連線、連線重用)時,Keep-Alive功能使客戶端到服 務器端的連線持續有效,當出現對伺服器的後繼請求時,Keep-Alive功能避免了建立或者重新建立連線。
通過使用keep-alive機制,可以減少tcp連線建立次數,也意味著可以減少TIME_WAIT狀態連線,以此提高效能和提高httpd伺服器的吞吐率(更少的tcp連線意味著更少的系統核心呼叫,socket的accept()和close()呼叫)。
5、 robots協議是什麼?
Robots協議(也稱為爬蟲協議、爬蟲規則、機器人協議等)也就是robots.txt,網站通過robots協議告訴搜尋引擎哪些頁面可以抓取,哪些頁面不能抓取。
Robots協議是網站國際網際網路界通行的道德規範,其目的是保護網站資料和敏感資訊、確保使用者個人資訊和隱私不被侵犯。因其不是命令,故需要搜尋引擎自覺遵守。
6、 列出幾種常見的關係型資料庫和非關係型資料庫?(每種至少兩個)
mysql,oracle mongoDB,redis
Oracle、Mysql、SQLServer、DB2 Redis MongoDB Cassandra
7、 記憶體洩露是什麼?如何避免?
指由於疏忽或錯誤造成程式未能釋放已經不再使用的記憶體的情況。
記憶體洩漏並非指記憶體在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤,失去了對該段記憶體的控制,因而造成了記憶體的浪費。
導致程式執行速度減慢甚至系統崩潰等嚴重後果。
有 __del__() 函式的物件間的迴圈引用是導致記憶體洩漏的主凶。
不使用一個物件時使用:del object 來刪除一個物件的引用計數就可以有效防止記憶體洩漏問題.
通過 Python 擴充套件模組 gc 來檢視不能回收的物件的詳細資訊
可以通過 sys.getrefcount(obj) 來獲取物件的引用計數,並根據返回值是否為 0 來判斷是否記憶體洩漏
Python的記憶體管理機制1.引用計數:通過引用計數來保持對記憶體中的變數跟蹤,Python內部記錄中所有在使用物件各有多少個引用。
Python中有個內部跟蹤變數叫做引用計數器,每個變數有多少個引用,簡稱引用計數。當物件被建立時就建立了一個引用計數。
當某個物件的引用計數為0時,物件就不在需要,就列入了垃圾回收佇列。
引用計數增加:1.物件被建立:x=4;2.另外的別人被建立:y=x;3.被作為引數傳遞給函式:foo(x);4.作為容器物件的一個元素:a=[1,x,'33'];
引用計數減少時:1.一個本地引用離開了它的作用域。比如上面的foo(x)函式結束時,x指向的物件引用減1;
2.物件的別名被顯式的銷燬:del x ;或者del y;
3.物件的一個別名被賦值給其他物件:x=789
4.物件從一個視窗物件中移除:myList.remove(x)
5.視窗物件本身被銷燬:del myList,或者視窗物件本身離開了作用域。
2.垃圾回收1.引用計數: 每個物件中都有ob-refcnt來做引用計數。當一個物件...,ob-refcnt就會增加,當引用的物件刪除,那麼ob-refcnt就會減少當ob-refcnt為零,就會釋放該物件的記憶體空間2.標記清除: 解決迴圈引用的問題。先按需分配,等到沒有空閒記憶體的時候,從暫存器和程式棧上的引用出發,遍歷所有物件和引用把所有能訪問的打標記,最後將沒有標記的物件釋放掉3.分代技術: 提高效率,提高垃圾回收的效率,按照存活時間,分成不同的集合。將記憶體塊按照其存活時間劃分為不同的集合。每個集合就稱為一個“代”,垃圾回收的頻率隨代的存活時間增大而減小。。Python預設定義分代物件集合,引用數越大,物件的存活時間越長
3.記憶體池機制
在Python中,大多數申請的都是小塊的記憶體,會執行大量的malloc和free操作。Python引入了一個記憶體池機制,用於管理對小塊記憶體的申請和釋放,即Pymalloc機制。
它將不用的記憶體放到記憶體池而不是返回給作業系統。1. 當申請的記憶體小於256位元組時,PyObject_Malloc會在記憶體池中申請記憶體;當申請的記憶體大於256位元組時,PyObject_Malloc的行為將蛻化為malloc的行為。當然,通過修改Python原始碼,我們可以改變這個預設值,從而改變Python的預設記憶體管理行為。2. 對於Python物件,如整數,浮點數和List,都有其獨立的私有記憶體池,物件間不共享他們的記憶體池。也就是說如果你分配又釋放了大量的整數,用於快取這些整數的記憶體就不能再分配給浮點數。
8、 列舉幾個常用的dom解析專案、外掛
xpath,xml
xml、libxml2 、lxml 、xpath
9、 常見的反爬蟲機制有哪些?
爬取過程中,生成多個headers,偽造;
通過headers反爬蟲:解決策略,偽造headers
基於使用者行為反爬蟲:動態變化去爬取資料,模擬普通使用者的行為
基於動態頁面的反爬蟲:跟蹤伺服器傳送的ajax請求,模擬ajax請求
動態爬取資料,模仿使用者行為;
1. 偽裝user agent
2.使用代理
3. 降低訪問頻率
4. 動態爬取資料,模擬使用者行為;或通過ajax請求進行模擬。
10、如何提高爬取效率?
爬蟲下載慢主要原因是阻塞等待發往網站的請求和網站返回;
1. 爬取方面,利用非同步io。2.處理方面,利用訊息佇列做生產者消費者模型
1. 採用非同步與多執行緒,擴大,電腦的cpu利用率;
2. 採用訊息佇列模式
3. 提高頻寬
1、樓梯問題
1.1、給一個樓梯,從最下面往上走,每次可以走1到n步,求總共有多少種走法?
1.2、給一個樓梯,從最下面往上走,每次可以走1步或2步,求總共有多少種走法?
1.3、給一個樓梯,從最下面往上走,每次可以走1步或2步或3步,求總共有多少種走法?
# 1、 給一個樓梯,從最下面往上走,每次可以走1或2步,求總共有多少種走法?
# 假設只有一個臺階,那麼只有一種跳法,那就是一次跳一級,f(1)=1;如果有兩個臺階,那麼有兩種跳法,第一種跳法是一次跳一級,第二種跳法是一次跳兩級,f(2)=2。
# 如果有大於2級的n級臺階,那麼假如第一次跳一級臺階,剩下還有n-1級臺階,有f(n-1)種跳法,假如第一次條2級臺階,剩下n-2級臺階,有f(n-2)種跳法。這就表示f(n)=f(n-1)+f(n-2)。def walk_stairs(stairs):
if stairs == 1:
return 1
if stairs == 2:
return 2
else:
return walk_stairs(stairs-1) + walk_stairs(stairs-2)
# 2、給一個樓梯,從最下面往上走,每次可以走1到n步,求總共有多少種走法?
# 上1個臺階 1
# 上2個臺階 2
# 上3個臺階 4
# 上4個臺階 8
# 上n個臺階 2^(n-1)
# 3、給一個樓梯,從最下面往上走,每次可以走1步或2步或3步,求總共有多少種走法?
# 上1個臺階 2^(1-1)
# 上2個臺階 2^(2-1)
# 上3個臺階 2^(3-1)
# f(n) = f(n-1) + f(n-2) + f(n-3)
2、 給一個字元陣列,字元包含a-z、1-9,比如:a b c 4 b 2 a c 1 1 3,求只出現一次的第一次出現的字元
str_list = ['a', 'b', 'c', 4, 'b', 2, 'a', 'c', 1, 1, 3]
def find_only_one(alist):
for string in alist:
count = alist.count(string)
if count == 1:
return string
return None
3、 有一個html文字字串,讓我取出<a href="提示我這個連結地址">sflkj</a>這個a標籤裡面的href的連結地址?
from bs4 import BeautifulSoup
text = "<a href='提示我這個連結地址'>sflkj</a>"
the_html = BeautifulSoup(text,features='lxml')
print(the_html.find('a').attrs['href'])
或:from lxml import etree
Html = "<a href='提示我這個連結地址'>sflkj</a>".content.decode()
Html = etree.Html(Html)
li_temp_list = Html.xpath("//a/@href")
4、 下面是一個單執行緒的程式碼,請改寫成多執行緒的:
start = "http://google.com"
queue = [start]
visited = {start}
while queue:
url = queue.pop(0)
print(url)
for next_url in extract_url(url):
if next_url notin visited:
queue.append(next_url)
visited.add(next_url)
-----------------------------------------
from concurrent.futures import ThreadPoolExecutor
start = "http://google.com"
queue = [start]
visited = {start}
pool = ThreadPoolExecutor(10)
def func(url):
for next_url in extract_url(url):
if next_url not in visited:
queue.append(next_url)
visited.add(next_url)
while queue:
url = queue.pop(0)
pool.submit(func,url)
pool.shutdown(wait=True)