python爬蟲面試遇到的問題

文章目錄

    • 1python基礎
      • 1.1 列表生成式和生成器的區別 ?
      • 1.2 如何不用任何循環快速篩掉列表中的奇數元素 ?
      • 1.3 map和reduce的用法
      • 1.4 裝飾器的作用
      • 1.5 Python中__new__與__init方法的區別
      • 1.6 python中的設計模式
      • 1.7 lambda函數,以及它有什么好處
    • 2 反爬問題
      • 2.1 如何處理封IP的反爬
      • 2.2 如何處理驗證碼
      • 2.3 代理問題
      • 2.4 驗證碼處理
      • 2.5 模擬登陸問題
    • 3 數據庫問題
      • 3.1 說幾個redis中的數據類型和命令
      • 3.2 MySQL中的inner join和left join的區別 ?
    • 4 爬蟲問題
      • 4.1 常用的網絡數據爬取方法
      • 4.2 設計一個基于session登錄驗證的爬蟲方案
    • 5 框架問題
      • 5.1 scrapy的基本結構(五個部分都是什么,請求發出去的整個流程)
      • 5.2 scrapy的去重原理 (指紋去重到底是什么原理)
      • 5.4 scrapy中間件有幾類,分別在哪里起的作用(面向切面編程)
      • 6 分布式
      • 6.1 分布式原理
      • 6.2 分布式如何判斷爬蟲已經停止了
      • 6.3 分布式去重原理
      • 6.4 分布式爬蟲的實現:
        • 例子1
        • 例子2
    • 7 模擬登錄
      • 7.1 selenium模擬登錄,遇到驗證碼:
      • 7.2 tesseract-OCR的在驗證碼識別中的重訓練與使用
      • 7.3 搭建IP代理池

1python基礎

1.1 列表生成式和生成器的區別 ?

  • 列表生成式和生成器都可以來生成一個列表。
  • 列表生成式生成的列表,所有元素對象被立即創建在內存中,當元素過多時,勢必會占用過多內存,
  • 要用到生成器,它即時創建一個生成器對象,未創建任何元素。生成器來生成一個列表,它不會立即創建大量的對象在內存中。
  • 生成器的缺點,沒有列表的方法,如append、len、index等等
  • 通過next方法來訪問其元素,可通過循環打印出所有的元素

1.2 如何不用任何循環快速篩掉列表中的奇數元素 ?

用內置函數filter配合匿名函數過濾掉數組中不符合條件的元素

print (filter(lambda x:x%2 ==0, [1,2,3,4,5]))
#[2,4]

1.3 map和reduce的用法

map
map()函數接收兩個參數,一個是函數,一個是Iterable。

例子1:
def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
print(list?)
# [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce

reduce:把一個函數作用在一個序列[x1, x2, x3, …]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

例子1:

from functools import reduce
def add(x, y):return x + y
print(reduce(add, [1, 3, 5, 7, 9]))
#25

1.4 裝飾器的作用

裝飾器本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,提高了代碼的復用性。比如,在函數調用前后自動打印日志,但又不希望修改now()函數的定義,這種在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)。

1.5 Python中__new__與__init方法的區別

_new_:它是創建對象時調用,會返回當前對象的一個實例,可以用_new_來實現單例

_init_:它是創建對象后調用,對當前對象的一些實例初始化,無返回值。

1.6 python中的設計模式

1.7 lambda函數,以及它有什么好處

lambda 表達式,通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數
lambda函數:首要用途是指點短小的回調函數

lambda [arguments]:expression
>>> a=lambdax,y:x+y
>>> a(3,11)

2 反爬問題

2.1 如何處理封IP的反爬

因為網絡上的免費代理平臺可用的IP數量太少,所以自己寫一個模塊去抓取平臺的IP來維護是沒有什么意義的。我選擇的是付費代理,通過使用平臺的api在本地動態維護一個IP緩存池來供給分布式架構的爬蟲節點使用。這個緩存池不需要做IP有效性驗證,因為我的爬蟲若下載某個Request徹底失敗后會把這個Request重新放回Request隊列,而且選擇一個好的代理平臺可以大大提高代理IP質量。我常用的是快代理。緩存池的IP被取走一個,池中的數量就減少一個,當數量少于M時,再從平臺獲取N個。

2.2 如何處理驗證碼

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

2.3 代理問題

(1)為什么會用到代理
(2)代理怎么使用(具體代碼,請求在什么時候添加的代理)
(3)代理失效了怎么處理

2.4 驗證碼處理

(1)登陸驗證碼處理
使用tesseract來識別,不過tesseract你要自行去訓練它,不然識別率出奇的低。

(2)爬取速度過快出現的驗證碼處理
(3)如何用機器識別驗證碼

2.5 模擬登陸問題

(1)模擬登陸流程
(2)cookie如何處理
(3)如何處理網站傳參加密的情況

3 數據庫問題

3.1 說幾個redis中的數據類型和命令

3.2 MySQL中的inner join和left join的區別 ?

INNER JOIN(內連接,或等值連接):取得兩個表中存在連接匹配關系的記錄。
LEFT JOIN(左連接):取得左表(table1)完全記錄,即使右表(table2)并無對應匹配記錄。

  • 擴展:RIGHT JOIN(右連接):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即使左表(table1)并無匹配對應記錄。

4 爬蟲問題

4.1 常用的網絡數據爬取方法

正則表達式,Beautiful Soup, lxml

4.2 設計一個基于session登錄驗證的爬蟲方案

5 框架問題

5.1 scrapy的基本結構(五個部分都是什么,請求發出去的整個流程)

5.2 scrapy的去重原理 (指紋去重到底是什么原理)

(1)scrapy本身自帶有一個中間件
(2)scrapy源碼中可以找到一個dupefilters.py去重器
(3)需要將dont_filter設置為False開啟去重,默認是True,沒有開啟去重
(4) 對于每一個url的請求,調度器都會根據請求得相關信息加密得到一個指紋信息,并且將指紋信息和set()集合中的指紋信息進行比對,如果set()集合中已經存在這個數據,就不在將這個Request放入隊列中
(5)如果set()集合中沒有存在這個加密后的數據,就將這個Request對象放入隊列中,等待被調度

5.4 scrapy中間件有幾類,分別在哪里起的作用(面向切面編程)

(1)、scrapy的中間件理論上有三種(Schduler Middleware,Spider Middleware,Downloader Middleware),在應用上一般有以下兩種:

1.爬蟲中間件Spider Middleware
主要功能是在爬蟲運行過程中進行一些處理.

2.下載器中間件Downloader Middleware
主要功能在請求到網頁后,頁面被下載時進行一些處理.

(2)、使用

  1.Spider Middleware有以下幾個函數被管理:- process_spider_input 接收一個response對象并處理,位置是Downloader-->process_spider_input-->Spiders(Downloader和Spiders是scrapy官方結構圖中的組件)- process_spider_exception spider出現的異常時被調用- process_spider_output 當Spider處理response返回result時,該方法被調用- process_start_requests 當spider發出請求時,被調用

位置是Spiders–>process_start_requests–>Scrapy Engine(Scrapy Engine是scrapy官方結構圖中的組件)

2.Downloader Middleware有以下幾個函數被管理

- process_request request通過下載中間件時,該方法被調用

- process_response 下載結果經過中間件時被此方法處理

- process_exception 下載過程中出現異常時被調用

  編寫中間件時,需要思考要實現的功能最適合在那個過程處理,就編寫哪個方法.中間件可以用來處理請求,處理結果或者結合信號協調一些方法的使用等.也可以在原有的爬蟲上添加適應項目的其他功能,這一點在擴展中編寫也可以達到目的,實際上擴展更加去耦合化,推薦使用擴展.

6 分布式

6.1 分布式原理

這里重要的就是我的隊列通過什么維護?
這里一般我們通過Redis為維護,Redis,非關系型數據庫,Key-Value形式存儲,結構靈活。
并且redis是內存中的數據結構存儲系統,處理速度快,提供隊列集合等多種存儲結構,方便隊列維護

如何去重?
這里借助redis的集合,redis提供集合數據結構,在redis集合中存儲每個request的指紋
在向request隊列中加入Request前先驗證這個Request的指紋是否已經加入集合中。如果已經存在則不添加到request隊列中,如果不存在,則將request加入到隊列并將指紋加入集合

如何防止中斷?如果某個slave因為特殊原因宕機,如何解決?
這里是做了啟動判斷,在每臺slave的Scrapy啟動的時候都會判斷當前redis request隊列是否為空
如果不為空,則從隊列中獲取下一個request執行爬取。如果為空則重新開始爬取,第一臺叢集執行爬取向隊列中添加request

如何實現上述這種架構?
這里有一個scrapy-redis的庫,為我們提供了上述的這些功能
scrapy-redis改寫了Scrapy的調度器,隊列等組件,利用他可以方便的實現Scrapy分布式架構

6.2 分布式如何判斷爬蟲已經停止了

查一下爬蟲的狀態:

spider.getStatus();//獲取爬蟲狀態

6.3 分布式去重原理

6.4 分布式爬蟲的實現:

例子1

  • (1).使用兩臺機器,一臺是win10,一臺是ubuntu16.04,分別在兩臺機器上部署scrapy來進行分布式抓取一個網站.

  • (2).ubuntu16.04的ip地址為39.106.155.194,用來作為redis的master端,win10的機器作為slave.

  • (3).master的爬蟲運行時會把提取到的url封裝成request放到redis中的數據庫:“dmoz:requests”,并且從該數據庫中提取request后下載網頁,再把網頁的內容存放到redis的另一個數據庫中“dmoz:items”.

  • (4).slave從master的redis中取出待抓取的request,下載完網頁之后就把網頁的內容發送回master的redis.

  • (5).重復上面的3和4,直到master的redis中的“dmoz:requests”數據庫為空,再把master的redis中的“dmoz:items”數據庫寫入到mongodb中.

  • (6).master里的reids還有一個數據“dmoz:dupefilter”是用來存儲抓取過的url的指紋(使用哈希函數將url運算后的結果),是防止重復抓取的.

例子2

參考:https://juejin.im/post/5b0ba020f265da09151f56c7#heading-12

7 模擬登錄

7.1 selenium模擬登錄,遇到驗證碼:

截圖,找到驗證碼的位置,進行識別

#因為驗證碼不能一次就正確識別,我加了循環,一直識別,直到登錄成功
while True:
#清空驗證碼輸入框,因為可能已經識別過一次了,里面有之前識別的錯的驗證碼
driver.find_element_by_name(“verificationCode”).clear()
# 截圖或驗證碼圖片保存地址
screenImg = “H:\screenImg.png”
# 瀏覽器頁面截屏
driver.get_screenshot_as_file(screenImg)
# 定位驗證碼位置及大小
location = driver.find_element_by_name(‘authImage’).location
size = driver.find_element_by_name(‘authImage’).size
#下面四行我都在后面加了數字,理論上是不用加的,但是不加我這截的不是驗證碼那一塊的圖,可以看保存的截圖,根據截圖修改截圖位置
left = location[‘x’]+530
top = location[‘y’]+175
right = location[‘x’] + size[‘width’]+553
bottom = location[‘y’] + size[‘height’]+200
# 從文件讀取截圖,截取驗證碼位置再次保存
img = Image.open(screenImg).crop((left, top, right, bottom))
#下面對圖片做了一些處理,能更好識別一些,相關處理再百度看吧
img = img.convert(‘RGBA’) # 轉換模式:L | RGB
img = img.convert(‘L’) # 轉換模式:L | RGB
img = ImageEnhance.Contrast(img) # 增強對比度
img = img.enhance(2.0) # 增加飽和度
img.save(screenImg)
# 再次讀取識別驗證碼
img = Image.open(screenImg)
code = pytesseract.image_to_string(img)
#打印識別的驗證碼
#print(code.strip())

7.2 tesseract-OCR的在驗證碼識別中的重訓練與使用

參考:
https://zhuanlan.zhihu.com/p/40178190

7.3 搭建IP代理池

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/273805.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/273805.shtml
英文地址,請注明出處:http://en.pswp.cn/news/273805.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ubuntu18 常用命令

文章目錄卸載和安裝卸載和安裝 1.打開一個終端,輸入dpkg --list ,按下Enter鍵,終端輸出以下內容,顯示的是你電腦上安裝的所有軟件。 2.安裝 dpkg –i name.deb 安裝一個 deb 包;在終端上輸入命令sudo apt-get --purge remove 包…

以嵌入式系統設計師考試成績,開始嵌入式博客之旅

http://www.rkb.gov.cn/jsj/cms/s_contents/download/s_dt201003110106.html 轉載于:https://www.cnblogs.com/yueqian-scut/p/3952268.html

SSH框架配置及Maven使用

1.SSH框架配置 1.1. SSH框架介紹 1.2. SSH框架配置 所需資源下載: l jdk; 從Oracle官方網站:http://www.oracle.com/technetwork/cn/java/javase/downloads/index.html下載jdk,win7是默認安裝在C:\Program Files (x86)\Java\jdk1.6.0_25路徑下…

cookie,session的區別和聯系(補充token)

文章目錄1 http為什么是無狀態的2 cookie 和session 的區別詳解3 token參考:備注: 博客文章僅限于學習,禁止商用1 http為什么是無狀態的 2 cookie 和session 的區別詳解 這些都是基礎知識,不過有必要做深入了解。先簡單介紹一下。 二者的定…

庫函數和系統調用的區別

前言 這是一對非常容易混淆的概念。對于用戶( 應用程序開發者 )來說,并不一定要嚴格區分其意義。因為在用戶看來,它們都是以C函數的形式出現的。但了解二者的區別對我們掌握整個計算機系統有很大幫助。 區別 1. 一部分庫函數實現需要使用系統調用( 如 pr…

Flask 從入門到熟悉(不敢稱為精通)

文章目錄2.1 Flask介紹及其安裝2.2 Virtualenv3.1 一個最小的應用3.2 外部課件服務器3.3 調試模式4.1 路由介紹4.2 變量規則4.3 構建URL4.4 HTTP 方法4 總結5.1 靜態文件5.2 渲染模板5.3 練習66.1 接收請求數據6.2 請求對象6.3 文件上傳6.4 Cookies6 總結77.1 重定向和錯誤7.2 …

Ext JS 5 beta版發布

原文:Announcing Public Beta of Ext JS 5我們非常高興的宣布,Sencha Ext JS 5 beta版本開始進行公測了。這個beta版本可以讓你、我們Sencha社區來對我們的Ext JS 5的工作進度進行評測。對于所以Ext JS開發人員,這事一個很好的機會來協助完成…

算法【二分查找】(數組)

1 .山脈數組的巔峰索引 信息 我們把符合下列屬性的數組 A 稱作山脈&#xff1a; A.length > 3 存在 0 < i < A.length - 1 使得A[0] < A[1] < … A[i-1] < A[i] > A[i1] > … > A[A.length - 1] 給定一個確定為山脈的數組&#xff0c;返回任何滿…

關于癌癥的十大謠言

最近&#xff0c;國外網站總結了西方社會中流行的十個關于癌癥的謠言&#xff0c;其中很多謠言在我們周圍也有廣泛的傳播。 謠言1&#xff1a;癌癥是人為導致的現代疾病 或許在公眾的認知里&#xff0c;癌癥在今天要比歷史上任何時期都重要。不過實際上&#xff0c;癌癥可不是一…

[python 進階] 第7章 函數裝飾器和閉包

文章目錄7.1 裝飾器基礎知識7.2 Python何時執行裝飾器7.3 使用裝飾器改進“策略”7.4 變量作用域(global)備注 -比較字節碼&#xff08;暫略&#xff09;7.5 閉包7.6 nonlocal聲明global和nonlocal的區別7.7 實現一個簡單的裝飾器7.8 標準庫中的裝飾器7.8.1 使用functools.lru_…

自制“低奢內”CSS3登入表單,包含JS驗證,請別嫌棄哦。

要求 必備知識 基本了解CSS語法,初步了解CSS3語法知識。和JS/JQuery基本語法。 開發環境 Adobe Dreamweaver CS6 演示地址 演示地址 預覽截圖(抬抬你的鼠標就可以看到演示地址哦): 制作步驟: 一, html結構 <div id"home"><form id"login" class…

class里面只能寫以下5種

轉載于:https://www.cnblogs.com/phplearnings/p/3650849.html

【排序】算法(python實現)

文章目錄python 排序算法1 插入排序1.1 直接插入排序算法思想1.2 希爾排序算法思想2. 選擇排序2.1 簡單選擇排序2.2 堆排序參考python 排序算法 1 插入排序 1.1 直接插入排序 算法思想 直接插入排序的核心思想就是&#xff1a;將數組中的所有元素依次跟前面已經排好的元素相…

OpenSSL漏洞補救辦法詳解(轉)

CVE-2014-0160漏洞背景 2014年4月7日OpenSSL發布了安全公告&#xff0c;在OpenSSL1.0.1版本中存在嚴重漏洞(CVE-2014-0160)。OpenSSL Heartbleed模塊存在一個BUG&#xff0c;問題存在于ssl/dl_both.c文件中的心跳部分&#xff0c;當攻擊者構造一個特殊的數據包&#xff0c;滿足…

SharePoint 自定義WebPart之間的連接

1、創建SharePoint解決方案&#xff0c;添加兩個WebPart分別用來發送和接收&#xff1b; 2、發送值的WebPart需要繼承自IWebPartField(當然&#xff0c;根據需要還可以選擇IWebPartField,IWebPartParameters,IWebPartRow,IWebPartTable&#xff0c;具體參見msdn)&#xff0c;原…

[python 進階] 9. 符合Python風格的對象

文章目錄9.1 對象表示形式9.2 再談向量類9.3 備選構造方法9.4 classmethod與staticmethod9.5 格式化顯示9.6 可散列的Vector2d什么是可散列的數據類型9.6 可散列的Vector9.7 Python的私有屬性和“受保護的”屬性9.8 使用 __slots__ 類屬性節省空間本章包含以下話題&#xff1a;…

android軟件獲取系統簽名

有時候有的功能必須要有系統簽名才能使用&#xff0c;例如調用系統自帶的Surface.screenShot方法時&#xff0c;就必須在androidManifest.xml里聲明android:sharedUserId"android.uid.system" 但是這個時候在編譯生成的apk很有可能無法安裝的情況 并且報這個錯誤&…

Python3中的可變與不可變類型

在描述變量是否是可變類型時&#xff0c;可變與否實際上說的是對變量進行“修改”時變量的內存地址是否會發生變化&#xff0c;而非值是否可變。在Python中&#xff0c;對不可變的變量進行“修改”實際上是重新賦值&#xff0c;對可變的變量進行修改才是真正的修改&#xff0c;…

python中帶*(單星號)的變量和**(雙星號)的變量

一、*args的使用方法 *args 用來將參數打包成tuple給函數體調用二、**kwargs的使用方法 **kwargs 打包關鍵字參數成dict給函數體調用注意點&#xff1a;參數arg、*args、**kwargs三個參數的位置必須是一定的。必須是(arg,*args,**kwargs)這個順序&#xff0c;否則程序會報錯。單…