超詳細的爬蟲面試題

Hello,我是 Alex 007,爲啥是007呢?因爲叫 Alex 的人太多了,再加上每天007的生活,Alex 007就誕生了。

今天呢,主要是跟大家分享一下花了兩天整理的爬蟲面試題,歡迎三連哦。

一. Requests模塊

1. 簡述爬蟲的概念

爬蟲,即網絡機器人,如果把互聯網理解爲一張巨大的蜘蛛網,那麼爬蟲就是在這張網上捕獵的蜘蛛,它會根據你給定的目標將資源保存下來,也就是持久化存儲。

這個過程其實就類似於我們瀏覽器上網,只不過將這個繁瑣的過程通過編寫程序模擬的形式,讓爬蟲去互聯網上抓取數據。

2. 爬蟲有幾種分類,使用場景是什麼?

通用爬蟲:通用爬蟲是搜索引擎爬蟲的重要組成部分,主要是將互聯網上的網頁下載到本地,再對這些網頁做相關處理(提取關鍵字、去掉廣告),最後提供一個用戶檢索接口。

聚焦爬蟲:聚焦爬蟲是根據指定的需求在通用爬蟲抓取到的網絡上提取目標數據。

增量式爬蟲:增量式爬蟲是用來檢測網站數據更新的情況,且可以將網站更新的數據進行爬取。

3. 簡述robots協議的概念與作用

robots協議是一種存放於網站根目錄下的ASCII編碼的文本文件,它通常告訴網絡蜘蛛,此網站中的哪些內容是不應被搜索引擎的漫遊器獲取的,哪些是可以被漫遊器獲取的。

因爲一些系統中的URL是大小寫敏感的,所以robots.txt的文件名應統一爲小寫。

如果想單獨定義搜索引擎的漫遊器訪問子目錄時的行爲,那麼可以將自定的設置合併到根目錄下的robots.txt,或者使用robots元數據(Metadata,又稱元數據)。

當一個搜索蜘蛛訪問一個站點時,它會首先檢查該站點根目錄下是否存在robots.txt,如果存在,搜索機器人就會按照該文件中的內容來確定訪問的範圍;如果該文件不存在,所有的搜索蜘蛛將能夠訪問網站上所有沒有被口令保護的頁面。

如果將網站視爲酒店裏的一個房間,robots.txt就是主人在房間門口懸掛的“請勿打擾”或“歡迎打掃”的提示牌。這個文件告訴來訪的搜索引擎哪些房間可以進入和參觀,哪些房間因爲存放貴重物品,或可能涉及住戶及訪客的隱私而不對搜索引擎開放。

但robots.txt是一個協議,而不是一個命令,也不是防火牆,如同守門人無法阻止竊賊等惡意闖入者。

4. 什麼是反爬機制和反反爬機制

反爬機制:門戶網站通過相應的策略和技術手段,防止爬蟲程序進行網站數據的爬取。

1. U-A 校驗
2. 限制訪問頻率
3. 驗證碼
4. 登錄驗證

反反爬機制:爬蟲程序通過相應的策略和技術手段,破解門戶網站的反爬蟲手段,從而爬取到相應的數據。

5. 簡述使用requests模塊進行數據爬取的大致流程

(1)指定url
(2)基於requests模塊發起請求
(3)獲取響應對象中的數據
(4)數據解析
(5)持久化存儲

6. 簡述使用requests模塊爬取ajax加載數據爬取的大致流程

(1)指定動態加載數據的url
(2)基於requests模塊發起請求
(3)獲取響應對象中的數據
(4)數據解析
(5)持久化存儲

7. 簡述User-Agent參數的作用

User Agent中文名爲用戶代理,是Http協議中的一部分,屬於請求頭的組成部分,User Agent也簡稱UA

User Agent向訪問網站提供發起請求的瀏覽器類型及版本、操作系統及版本、瀏覽器內核、等信息的標識。

通過這個標識,用戶所訪問的網站可以顯示不同的排版從而爲用戶提供更好的體驗或者進行信息統計。

在使用爬蟲獲取數據的時候,主要是想要獲取網站的數據,而有些網站則是不想讓我們的爬蟲進行獲取,所以我們會對爬蟲進行各種各樣的僞裝,UA僞裝就是其中一種收單,讓對方識別我們爲爬蟲的概率更小,這樣爬取到想要的數據的概率就越大。

8. 在requests模塊中接觸過哪些反爬機制

(1)驗證碼

爬蟲採集器優化方案:使用打碼平臺識別驗證碼。

(2)限制IP訪問頻率

分析:沒有哪個正常人可以在一秒鐘內能訪問相同網站數十次次,除非是程序訪問,也就是搜索引擎爬蟲和爬蟲採集器。

弊端:一刀切,這同樣會阻止搜索引擎對網站的收錄

適用網站:不太依靠搜索引擎的網站

爬蟲採集器優化方案:減少單位時間的訪問次數,減低採集效率

(3)UA校驗

分析:服務器端通過檢驗請求的User-Agent來判斷是瀏覽器還是爬蟲程序。

爬蟲採集器優化方案:製作UA僞裝

(4)登錄校驗

分析:搜索引擎爬蟲不會對每個需要登錄的網站設計登錄程序,但爬蟲採集器可以針對某個網站設計模擬用戶登錄提交表單行爲。

適用網站:極度討厭搜索引擎,且想阻止大部分採集器的網站

爬蟲採集器優化方案:製作擬用戶登錄提交表單行爲的模塊

(5)動態加載頁面

分析:有一部分網站,需要爬取的數據是通過Ajax請求得到的,根據不同的情況動態加載數據。

爬蟲採集器優化方案:基於Selenium+PhantomJS模擬瀏覽器請求。

(6)數據加密

對部分數據進行加密的,可以使用selenium進行截圖,使用python自帶的pytesseract庫進行識別,但是比較慢,最直接的方法是找到加密的方法進行逆向推理。

9. 介紹下requests模塊中getpost方法常用參數的作用

GET:

# 封裝get請求參數
prams = {
    'query':word,
    'ie':'utf-8'
}

# 定製請求頭信息,相關的頭信息必須封裝在字典結構中
headers = {
    # 定製請求頭中的User-Agent參數,當然也可以定製請求頭中其他的參數
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
}

response = requests.get(url=url,headers=headers,params=param)

POST:

# 定製post請求攜帶的參數(從抓包工具中獲取)
data = {
    'cname':'',
    'pid':'',
    'keyword':'北京',
    'pageIndex': '1',
    'pageSize': '10'
}

# 定製請求頭信息,相關的頭信息必須封裝在字典結構中
headers = {
    # 定製請求頭中的User-Agent參數,當然也可以定製請求頭中其他的參數
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36',
}

# 發起post請求,獲取響應對象
response = requests.get(url=url,headers=headers,data=data)

10. 簡述session的創建流程及其該對象的作用

# 創建一個session對象,該對象會自動將請求中的cookie進行存儲和攜帶
session = requests.session()
# cookie由服務器創建並交給客戶端瀏覽器保存,會話跟蹤技術,再次訪問時,服務器就可以區分客戶端瀏覽器
# 使用session發送請求,目的是爲了將session保存該次請求中的cookie
session.post(url=post_url,data=formdata,headers=headers)

get_url = 'http://www.renren.com/960481378/profile'
# 再次使用session進行請求的發送,該次請求中已經攜帶了cookie
response = session.get(url=get_url,headers=headers)

11. 簡述如何使用requests模塊進行模擬登錄,並抓取登錄成功後的某個二級頁面數據。

結合session = requests.post.session(),先登陸成功

在瀏覽器獲取post請求的參數response = requests.post(url=url,data=data,headers=headers)

然後獲取個人頁面urlparams = {},獲取get請求參數response = requests.get(url=url,params=params,headers=headers)

最後獲取響應對象的頁面數據page_text = response.text

12. 簡述如何使用requests模塊設置代理IP

1、在使用requests模塊–get post —proxy

#不同的代理IP
proxy_list = [
    {"http": "112.115.57.20:3128"},
    {'http': '121.41.171.223:3128'}
]
# 隨機獲取UA和代理IP
header = random.choice(header_list)
proxy = random.choice(proxy_list)

# 設置代理
response = requests.get(url=url,headers=header,proxies=proxy)

2、在scrapy框架下使用下載中間件

1.在下載中間件中攔截請求

2.將攔截到的請求的IP修改成某一代理IP

3.在配置文件(settings.py)中開啓下載中間件

二. 數據解析

1. 簡述使用在使用正則進行解析時用到的re.Sre.M的作用和區別

re.I: 忽略大小寫
re.M :多行匹配
re.S :單行匹配

2. 簡述如何使用xpath進行數據解析

(1)一般情況下

  1. 導入:from lxml import etree
  2. 實例化一個etree對象並將瀏覽器網頁數據註冊到對象中,本地數據使用etree.parse,網絡數據使用etree.HTML
  3. 編寫xpath表達式

(2)Scrapy框架中response對象已經封裝好了xpath方法

3. 簡述如何使用bs4進行數據解析

bs4裏面有一個類BeautifulSoup,通過這個類將網頁html格式字符串實例化一個對象,然後通過對象的方法來進行查找指定元素。

將本地html文件轉化爲對象:

soup = BeautifulSoup(open('soup.html', encoding='utf8'), 'lxml')

**根據標籤名查找:**只能查找得到第一個符合要求的節點,是一個bs4自己封裝類的對象

soup.a

獲取屬性
soup.a.attrs 獲取得到所有屬性和值,是一個字典
soup.a.attrs['href'] 獲取指定的屬性值
soup.a['href'] 簡寫形式

獲取文本:

soup.a.string
soup.a.text
soup.a.get_text()

如果標籤裏面還有標籤,那麼string獲取就是空,而後兩個獲取的是純文本內容。

find_all方法

返回的是一個列表,列表裏面都是節點對象。

soup.find_all('a') 找到所有a
soup.find_all('a', limit=2) 提取符合要求的前兩個a
soup.find_all(['a', 'li']) 查找得到所有的a和li
soup.find_all('a', class_='xxx')查找得到所有class是xxx的a
soup.find_all('li', class_=re.compile(r'^xiao'))查找所有的class以xiao開頭的li標籤

select方法
id選擇器 #dudu
類選擇器 .xixi
標籤選擇器 div a h1

4. xpath方法返回值類型是什麼

xpath函數返回的總是一個列表----列表裏面是選擇器對象。

可以用索引、和切片進行處理。

5. 在xpath中如何/text()//text()的區別是什麼

(1)/text()表示獲取某個標籤下的文本內容

(2)//text()表示獲取某個標籤下的文本內容和所有子標籤下的文本內容

6. id爲su的div標籤有一個子標籤ul,ul下有十個li標籤,每一個li標籤下都有一個a標籤,如何編寫xpath表達式可以解析到a標籤的href屬性值

li = response.xpath('//div[@id="su"]/ul/li')
for i in li:
  i.xpath('./a/@href').extract_first()

7. classwddiv標籤有一個子標籤ulul下有十個li標籤,每一個li標籤下都有一個a標籤,如何編寫xpath表達式可以解析到a標籤中的文本內容

lis=response.xpath('//div[@class="wd"]/ul/li')
for li in lis:
  a=li.xpath('./a/text()').extract_first()

8. 簡述extract()extract_first()的區別

首先,只有在在Scrapy中才有extract_first()extract(),然後extract()方法返回的是一個數組List,裏面包含了多個string,就算只有一個string返回的也是列表的形式,而extract_first()方法返回的是List數組裏面的第一個string字符串。

9. 簡述BeautifulSoup模塊中find和findall方法的區別

find:找到第一個符合要求的標籤

find_all:找到所有符合要求的標籤

10. 簡述BeautifulSoup模塊中select方法的使用

bs4裏面有一個類BeautifulSoup,通過這個類將網頁html格式字符串實例化一個對象,然後通過對象的方法來進行查找指定元素。

select方法
id選擇器 #dudu
類選擇器 .xixi
標籤選擇器 div a h1

11. 簡述xpath插件的作用

就可以直接將xpath表達式作用到瀏覽器的網頁當中 ,進行驗證。

三. Scrapy 框架

1. 簡述scrapy框架的安裝流程

pip install -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com twisted

pip install -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com pywin32

pip install -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com scrapy
  1. twisted
    Twisted 是用 Python 實現的基於事件驅動的網絡引擎框架,提供了允許阻塞行爲但不會阻塞代碼執行的方法,比較適合異步的程序。

  2. pywin32
    pywin32 主要的作用是方便 Python 開發者快速調用 Windows API的一個模塊庫。

1.1. 爲什麼要使用scrapy框架?

首先,Scrapy是基於twisted的異步IO框架,並且是純Python實現的爬蟲框架,在性能方面有很大的優勢。

其次,在Scrapy中可以加入requestsBeautifulSoup,內置的cssselectorxpath使用非常方便,還提供了很多其它的內置功能。

最後,Scrapy是默認深度優先的,並且可以實現高併發的數據爬取,更加容易構建大規模的抓取項目。

2. scrapy中持久化操作有幾種形式,分別如何實現?

(1)基於終端指令的持久化存儲

首先要保證parse方法返回一個可迭代類型的對象,然後可以使用如下指令完成數據存儲的功能:

scrapy crawl baiDu -o baidu.json

(2)基於管道的持久化存儲

  1. 將爬蟲文件爬取到的數據封裝到items對象中
  2. 使用yielditems對象提交給pipelines管道持久化存儲
  3. 管道文件中的process_item方法接收並處理爬蟲文件提交過來的item對象
  4. 配置文件settings.py中開啓管道

3. 簡述start_requests方法的作用

源碼:

def start_requests(self):
    for url in self.start_urls:
        yield self.make_requests_from_url(url)

首先由start_requestsstart_urls中的每一個url發起請求(make_requests_from_url),這個請求會被parse接收。

4. 在scrapy中如何進行post請求發送

scrapy中可以通過scrapy.FormRequest方法發送post請求,參數爲formdata

yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse)   

5. 在scrapy中如何手動進行一個get請求的發送

scrapy中可以通過scrapy.Request方法發送get請求:

yield scrapy.Request(url=url,callback=self.parse)

6. 簡述管道文件的作用

Scrapy中,從每一個URL中爬取的數據封裝成一個Response對象,作爲參數返回給parse方法或自定義的回調函數,parse方法解析Responseitem,然後傳遞給管道,在pipelines.py文件中提取item中的內容,進行數據的持久化處理。

7. 簡述Request方法中callback參數的作用

爲當次request方法指定回調函數,參數就是本次請求的返回結果。

8. 簡述Request方法中meta參數的作用

ScrapyRequest方法的meta參數要傳入一個字典,主要是傳遞數據用,meta是隨着Request產生時傳遞的嗎,比如meta = {‘key1’:value1},如果想要在下一個函數中取出value1,只需要使用meta['key1']即可。

9. 簡述下載中間件的作用

下載中間件是位於Scrapy引擎和下載器之間的一層組件,用於處理請求,可以對請求設置隨機的User-Agent,設置隨機的代理IP,目的就在於防止應對網站的反爬策略。

下載器完成下載任務之後,在將Response傳遞給引擎之前,下載中間件可以對Response進行一系列處理,比如進行解壓等操作。

下載中間件需要註冊才能使用,在settings.py文件中設置DOWNLOADER_MIDDLEWARES,設置爲一個字典,鍵爲中間件類的路徑,值爲其中間件的順序。

9.1. 簡述蜘蛛中間件的作用

蜘蛛中間件是介於ScrapyEngineSpider之間的鉤子框架,主要工作是處理蜘蛛的響應輸入和請求輸出。

9.2. 簡述調度中間件的作用

Scheduler Middlewares是介於ScrapyEngineScheduler之間我的中間件,主要工作是處理從ScrapyEngine發送到Scheduler的請求和響應。

10. 簡述如何設置scrapy項目的代理IP

(1)找一些代理IP添加到settings.py
(2)在middlewares.py中添加代理中間件:

class ProxyMiddleware(object):
    def __init__(self, ip):
        self.ip = ip
        
    @classmethod
    def from_crawler(cls, crawler):
        return cls(ip=crawler.settings.get('PROXIES'))

    def process_request(self, request, spider):
        ip = random.choice(self.ip)
        request.meta['proxy'] = ip

(3)在settings.py中註冊代理IP中間件

11. 簡述CrawlSpider中鏈接提取器的作用

link = LinkExtractor(allow=r'/all/hot/recent/\d+')

Step 1. 實例化一個鏈接提取器對象

Step 2. 從起始url響應頁面中按照正則表達式提取指定url

Step 3. 將鏈接提取器註冊給規則解析器

12. 簡述CrawlSpider中規則解析器的作用

Step 1. 實例化一個規則提取器對象

Step 2. 規則解析器接收鏈接提取器發送的鏈接並對這些鏈接發起請求

Step 3. 根據指定的規則對返回頁面內容指定解析規則callback,通過follow確定是否遞歸獲取鏈接

Rule(link, callback='parse_item', follow=False),

13. 簡述scrapy核心組件的工作原理

在這裏插入圖片描述

  • Spiders爬蟲
    爬蟲就是幹活的,編寫業務邏輯代碼,從特定的網頁中提取自己需要的信息,每個Spider負責處理一個(些)特定網站。

  • Scrapy Engine引擎
    引擎用於處理整個Scrapy系統的數據流,觸發事務等,是整個框架的核心。

  • Scheduler調度器
    調度器用來接收引擎發過來的請求並將其壓入隊列中,需要時彈出,可以簡單理解爲url調度器,可以去除重複的url

  • Downloader下載器
    下載器顧名思義就是用於下載網頁並將內容返回給SpidersScrapy的下載器是建立在Twisted高效異步模型上的。

  • Item、Pipeline管道
    管道負責處理Spiders從網頁中抽取的實體並做持久化處理,同時可以驗證實體的有效性、清楚無用信息。

Scrapy運行流程

  1. 引擎打開一個域名,蜘蛛處理這個域名,並讓蜘蛛獲取第一個爬取的URL

  2. 引擎從蜘蛛那獲取第一個需要爬取的URL,然後作爲請求在調度中進行調度。

  3. 引擎從調度那獲取接下來進行爬取的頁面。

  4. 調度將下一個爬取的URL返回給引擎,引擎將他們通過下載中間件發送到下載器。

  5. 當網頁被下載器下載完成以後,響應內容通過下載中間件被髮送到引擎。

  6. 引擎收到下載器的響應並將它通過蜘蛛中間件發送到蜘蛛進行處理。

  7. 蜘蛛處理響應並返回爬取到的項目,然後給引擎發送新的請求。

  8. 引擎將抓取到的內容發送到項目管道做持久化處理,並向調度發送新的請求。

  9. 系統重複第二步後面的操作,直到調度中沒有請求,然後斷開引擎與域之間的聯繫。

14. 原生scrapy框架爲何不能實現分佈式

其一:因爲多臺機器上部署的scrapy會各自擁有各自的調度器,這樣就使得多臺機器無法分配start_urls列表中的url。(多臺機器無法共享同一個調度器)

其二:多臺機器爬取到的數據無法通過同一個管道對數據進行統一的數據持久出存儲。(多臺機器無法共享同一個管道)

15.0. 簡述一下什麼是分佈式

當項目需要計算的數據量非常大,任務又非常多,一臺機器搞不定或者效率非常低的時候,就需要多臺機器共同協作,最後將所有機器完成的任務彙總在一起,從而完成大量的任務。

比如分佈式爬蟲,就是將一個項目拷貝到多臺電腦上,將多臺主機組合起來共同完成一個爬取任務,這樣可以大大提高爬取的效率。

15. 簡述基於scrapy-redis分佈式的流程

分佈式爬蟲scrapy+redis入門

16. 簡述一下scrapyselenium的使用

Engineurl對應的請求提交給Downloader之後,Downloader對目標網頁進行下載,然後將下載到的頁面數據封裝成response之後返回給Engine,而Engine再將response轉交給Spider

Spider接收到的response對象中存儲的頁面數據是沒有動態加載的,如果想獲取動態加載的數據,則需要在Downloader Middlewares中對Downloader返回給Engineresponse響應對象進行攔截,將其內部存儲的頁面數據替換成攜帶動態加載數據的內容。

替換的操作就需要用到selenium來模擬瀏覽器了,在Scrapy中使用selenium的流程如下:

(1)重寫爬蟲的構造方法,在該方法中使用selenium實例化一個瀏覽器對象;
(2)重寫爬蟲文件的close方法,在其內部關閉瀏覽器對象,在爬蟲結束時被調用;
(3)重寫Downloader Middlewaresprocess_response方法,讓改方法對相應對象進行攔截和替換response中存儲的頁面數據;
(4)在配置文件中開啓下載中間件。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章