1. 程式人生 > >[爬蟲面試] 總結一些爬蟲工程師遇到的面試題(真實)

[爬蟲面試] 總結一些爬蟲工程師遇到的面試題(真實)

前言:

    說幾句,座標CQ,爬蟲工程師的需求在這個二線城市真的是太少了。

正文:

        NO.1 :列表生成式和生成器的區別 ?
        NO.2 :如何不用任何迴圈快速篩掉列表中的奇數元素 ?
        NO.3 :map和reduce的用法 ?
        這幾個問題的答案作如下統一回答:
#列表生成式
print list(range(11))
#列表生成式第二種寫法
a = [x for x in range(11)]

#使用內建filter函式過濾列表a中不滿足lambda函式的元素,即過濾掉奇數,留下偶數
print filter(lambda x: x%2==0 , a)  #[0, 2, 4, 6, 8, 10]

'''
列表生成式直接生成一個列表,所有元素物件被立即建立在記憶體中,當元素過多時,勢必會佔用過多記憶體,
不可取,要用到生成器,它即時建立一個生成器物件,未建立任何元素
'''
#生成器來生成一個列表,它不會立即建立大量的物件在記憶體中
b = (x for x in range(11))

#生成器的缺點,沒有列表的方法,如append、len、index等等
#print len(b)   #丟擲異常,生成器沒有__len__屬性,檢視不了列表長度

#通過next方法來訪問其元素
print b.next(),b.next()  #0 1

#可通過迴圈打印出所有的元素
for i in b:print i

'''
第二種生成器寫法,使用yield:迭代器 封裝於函式內
'''
def generator_(n):
    for i in range(n):
        yield i
#此時這個函式已經是一個生成器了
print generator_(11).next()

#使用內建函式filter配合匿名函式過濾掉陣列中不符合條件的元素
print filter(lambda x:x%2 ==0, [1,2,3,4,5]) #[2,4]
#也可以把以下函式作為第一個引數傳入
def get_2(n):
    return n%2==0
print filter(get_2, [1,2,3,4,5]) #[2,4]
'''
擴充套件;
可以直接作用於for迴圈的資料型別有以下幾種: 
一類是集合資料型別,如list、tuple、dict、set、str等; 
一類是generator,包括生成器和帶yield的generator function。 
這些可以直接作用於for迴圈的物件統稱為可迭代物件:Iterable。 
可以使用isinstance()判斷一個物件是否是Iterable物件:
'''

from collections import Iterable #這個是可迭代物件
for i in ['123',[],(1,),set(),{}]:
    print isinstance(i,Iterable)  #都是true

from collections import Iterator #這個是迭代器

#可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator
print isinstance((i for i in range(11)),Iterator)  #True

#用Iter函式把可迭代物件變成迭代器
print isinstance(iter('123'),Iterator)

# reversed將可迭代物件反轉為一個迭代器
print  reversed([1,2,3]).next()

'''
高階函式用法:reduce,map
'''
#map
#使用函式來處理序列中的元素 :包含數字的元組、列表
res = map(lambda n:n*2, range(10))
print res  #[0, 2, 4, 6...

#可以接收2個數序列,生成一個列表
print map(lambda x,y:(x,y) , [1,2,3],[4,5,6]) #[(1, 4), (2, 5), (3, 6)]

#reduce
#使用函式來累積處理序列中的元素,可實現階乘、求陣列內的數字和
print reduce(lambda x,y:x*y , [1,2,3,4])  #24
print reduce(lambda x,y:x+y , [1,2,3,4])  #10  ,sum([1,2,3])更快

print reduce(lambda x,y:x+y ,'123','123')  #123123
print reduce(lambda x,y:x+y , ['x','y','z'])  #xyz
        NO.4:  裝飾器的作用 ?             答:裝飾器本質上是一個Python函式,它可以讓其他函式在不需要做任何程式碼變動的前提下增加額外功能,提高了程式碼的複用性。

        NO.5: 如何處理封IP的反爬 ?             答:因為網路上的免費代理平臺可用的IP數量太少,所以自己寫一個模組去抓取平臺的IP來維護是沒有什麼意義的。我選擇的是付費代理,通過使用平臺的api在本地動態維護一個IP快取池來供給分散式架構的爬蟲節點使用。這個快取池不需要做IP有效性驗證,因為我的爬蟲若下載某個Request徹底失敗後會把這個Request重新放回Request佇列,而且選擇一個好的代理平臺可以大大提高代理IP質量。我常用的是快代理。快取池的IP被取走一個,池中的數量就減少一個,當數量少於M時,再從平臺獲取N個。(具體可檢視我的
另一篇文章

        NO.6: 如何處理驗證碼 ?
            答:簡單的驗證碼可以通過預處理(灰度、二值化、去除乾燥點)驗證碼圖片再使用tesseract庫來識別;複雜一點的則接入付費平臺識別。當然,如果這個目標網站的app端沒有驗證碼的話,會優先通過app端爬取。

        NO.7: 說幾個redis中的資料型別和命令
            答:字串、列表、set集合;set key 123,,,lpush key 1 2 3,,,sadd key 1 2 3

        NO.8: MySQL中的inner join和left join的區別 ?
            答:INNER JOIN(內連線,或等值連線):取得兩個表中存在連線匹配關係的記錄。                    LEFT JOIN(左連線):取得左表(table1)完全記錄,即是右表(table2)並無對應匹配記錄。                    擴充套件:RIGHT JOIN(右連線):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)並無匹配對應記錄。(可參考 菜鳥教程
        待續。