一、接觸過幾種爬蟲模塊
urllib requestscss
二、robots協議是什麼?
網站有一些數據不想被爬蟲程序爬取,能夠編寫robots協議文件,明確指明哪些內容能夠爬取哪些不能夠爬取。
在Scrapy框架中在settings.py文件中使用了硬性語法對該協議進行了生效python
三、如何處理驗證碼?
使用三方的打碼平臺好比:雲打碼平臺、打碼兔,能夠用來處理驗證碼。
四、掌握幾種數據解析的方式?
re、xpath(最經常使用)、bs4(python獨有)
五、如何爬取動態加載的頁面數據?
selenium; ajax:抓包工具抓取異步發起的請求(url)
六、接觸過哪些反爬機制?如何處理?
robots協議、UA、封IP、驗證碼、動態數據加載、數據加密、token
處理:
配置不遵照robots協議、假裝User-Agent、代理IP更換、打碼平臺對驗證碼識別、
selenium處理或者使用抓包工具去抓取動態加載的AJAX請求數據包、
按照已知的各類加密方式進行解密、去前臺頁面進行token值的查找手動放入請求攜帶的參數中。
七、在Scrapy中接觸過幾種爬蟲類?
Spider、CrawlSpider(連接提取器和規則解析器)、RedisCrawlSpider、RedisSpider
八、如何實現分佈式流程?
必需要經過scrapy-redis組件來實現,能夠由RedisCrawlSpider、RedisSpider這兩種類分別實現。
9.簡述 requests模塊的做用及基本使用?
Requests 自稱 "HTTP for Humans",說明使用更簡潔方便。
Requests支持HTTP鏈接保持和鏈接池,支持使用cookie保持會話,支持文件上傳,支持自動肯定響應內容的編碼,
支持國際化的 URL 和 POST 數據自動編碼。
十、requests模塊參數,data與json參數的區別?
在經過requests.post()進行POST請求時,傳入報文的參數有兩個,一個是data,一個是json。
data與json既能夠是str類型,也能夠是dict類型。
區別:
一、無論json是str仍是dict,若是不指定headers中的content-type,默認爲application/json
二、data爲dict時,若是不指定content-type,默認爲application/x-www-form-urlencoded,至關於普通form表單提交的形式
三、data爲str時,若是不指定content-type,默認爲application/json
四、用data參數提交數據時,request.body的內容則爲a=1&b=2的這種形式,用json參數提交數據時,request.body的內容則爲'{"a": 1, "b": 2}'的這種形式
十一、簡述 beautifulsoup模塊的做用及基本使用?
和 lxml 同樣,Beautiful Soup 也是一個HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 數據。
lxml 只會局部遍歷,而Beautiful Soup 是基於HTML DOM的,會載入整個文檔,解析整個DOM樹,所以時間和內存開銷都會大不少,因此性能要低於lxml。
十二、簡述 seleninu模塊的做用及基本使用?
Selenium 能夠根據咱們的指令,讓瀏覽器自動加載頁面,獲取須要的數據,甚至頁面截屏,或者判斷網站上某些動做是否發生。
Selenium 本身不帶瀏覽器,不支持瀏覽器的功能,它須要與第三方瀏覽器結合在一塊兒才能使用。
1三、scrapy框架中各組件的工做流程?
Scrapy Engine: 這是引擎,負責Spiders、ItemPipeline、Downloader、Scheduler中間的通信,信號、數據傳遞等等
Scheduler(調度器): 它負責接受引擎發送過來的requests請求,並按照必定的方式進行整理排列,入隊、並等待Scrapy Engine(引擎)來請求時,交給引擎。
Downloader(下載器):負責下載Scrapy Engine(引擎)發送的全部Requests請求,並將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spiders來處理
Spiders:它負責處理全部Responses,從中分析提取數據,獲取Item字段須要的數據,並將須要跟進的URL提交給引擎,再次進入Scheduler(調度器)
Item Pipeline:它負責處理Spiders中獲取到的Item,並進行處理,好比去重,持久化存儲(存數據庫,寫入文件,總之就是保存數據用的)
Downloader Middlewares(下載中間件):你能夠看成是一個能夠自定義擴展下載功能的組件
Spider Middlewares(Spider中間件):你能夠理解爲是一個能夠自定擴展和操做引擎和Spiders中間‘通訊‘的功能組件
(好比進入Spiders的Responses;和從Spiders出去的Requests) ajax
1四、在scrapy框架中如何設置代理(兩種方法)?redis
一.使用中間件DownloaderMiddleware進行配置
1.在Scrapy工程下新建「middlewares.py」
# Importing base64 library because we'll need it ONLY in case if the proxy we are going to use requires authentication
import base64
# Start your middleware class
class ProxyMiddleware(object):
# overwrite process request
def process_request(self, request, spider):
# Set the location of the proxy
request.meta['proxy'] = "http://YOUR_PROXY_IP:PORT"
# Use the following lines if your proxy requires authentication
proxy_user_pass = "USERNAME:PASSWORD"
# setup basic authentication for the proxy
encoded_user_pass = base64.encodestring(proxy_user_pass)
request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_pass
2.在項目配置文件裏(./pythontab/settings.py)添加
DOWNLOADER_MIDDLEWARES = {
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 110,
'pythontab.middlewares.ProxyMiddleware': 100,
}
注意:
1.proxy必定是要寫號http://前綴
2.若是代理有用戶名密碼等就須要在後面再加上一些內容
二.直接在爬蟲程序中設置proxy字段
能夠直接在本身具體的爬蟲程序中設置proxy字段,直接在構造Request裏面加上meta字段便可
class QuotesSpider(scrapy.Spider):
name = "quotes"
def start_requests(self):
urls = [
'http://quotes.toscrape.com/page/1/',
'http://quotes.toscrape.com/page/2/',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse, meta={'proxy': 'http://proxy.yourproxy:8001'})
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').extract_first(),
'author': quote.css('span small::text').extract_first(),
'tags': quote.css('div.tags a.tag::text').extract(),
}
--------------
import scrapy
class ProxySpider(scrapy.Spider):
name = 'proxy'
allowed_domains = ["httpbin.org"]
def start_requests(self):
url = 'http://httpbin.org/get'
proxy = '127.0.0.0:8000'
proxies = ""
if url.startswith("http://"):
proxies = "http://"+str(proxy)
elif url.startswith("https://"):
proxies = "https://"+str(proxy)
#注意這裏面的meta={'proxy':proxies},必定要是proxy進行攜帶,其它的不行,後面的proxies必定 要是字符串,其它任何形式都不行
yield scrapy.Request(url, callback=self.parse,meta={'proxy':proxies})
def parse(self,response):
print(response.text)
1五、scrapy框架中如何實現大文件的下載?
利用scrapy下載大量大尺寸圖片及視頻時有時會報錯,顯示放棄重試
緣由:
這是因爲scrapy併發請求過多,默認狀況下會同時下載16個文件,而鏈接時間默認超過三分鐘就會丟失。
就是說若是三分鐘以內你的網速無法支持你同時下載完16個文件的話就會形成這個問題。
解決方法:
在settings.py中將默認併發鏈接數調小或者將timeout時間調大
CONCURRENT_REQUESTS = 2
DOWNLOAD_TIMEOUT=1800
此時併發請求被調成2, 等待時間被1800秒,通常的小視頻和圖片是沒有問題了。數據庫
1六、scrapy中如何實現限速?
自動限速:
限制爬蟲速度,對對方服務器友好些,防止被識別
在setting.py開啓相關擴展:
自動限速設定:
AUTOTHROTTLE_ENABLED = True
設定爬取速度:
DOWNLOAD_DELAY = 1 #單位爲秒json
1七、scrapy中如何實現暫定爬蟲?
1.進入到scrapy項目裏
二、在scrapy項目裏建立保存記錄信息的文件 zant/001
三、執行命令:
scrapy crawl 爬蟲名稱 -s JOBDIR=保存記錄信息的路徑
如:scrapy crawl cnblogs -s JOBDIR=zant/001
執行命令會啓動指定爬蟲,而且記錄狀態到指定目錄
爬蟲已經啓動,咱們能夠按鍵盤上的ctrl+c中止爬蟲,中止後咱們看一下記錄文件夾,會多出3個文件,
其中的requests.queue文件夾裏的p0文件就是URL記錄文件,這個文件存在就說明還有未完成的URL,當全部URL完成後會自動刪除此文件
當咱們從新執行命令:scrapy crawl cnblogs -s JOBDIR=zant/001 時爬蟲會根據p0文件從中止的地方開始繼續爬取。瀏覽器
1八、scrapy中如何進行自定製命令?服務器
【同時運行多個scrapy爬蟲的幾種方法(自定義scrapy項目命令)】
一、建立commands目錄
mkdir commands
注意:commands和spiders目錄是同級的
二、在commands下面添加一個文件crawlall.py
這裏主要經過修改scrapy的crawl命令來完成同時執行spider的效果。
from scrapy.commands import ScrapyCommand
from scrapy.crawler import CrawlerRunner
from scrapy.utils.conf import arglist_to_dict
class Command(ScrapyCommand):
requires_project = True
def syntax(self):
return '[options]'
def short_desc(self):
return 'Runs all of the spiders'
def add_options(self, parser):
ScrapyCommand.add_options(self, parser)
parser.add_option("-a", dest="spargs", action="append", default=[], metavar="NAME=VALUE",
help="set spider argument (may be repeated)")
parser.add_option("-o", "--output", metavar="FILE",
help="dump scraped items into FILE (use - for stdout)")
parser.add_option("-t", "--output-format", metavar="FORMAT",
help="format to use for dumping items with -o")
def process_options(self, args, opts):
ScrapyCommand.process_options(self, args, opts)
try:
opts.spargs = arglist_to_dict(opts.spargs)
except ValueError:
raise UsageError("Invalid -a value, use -a NAME=VALUE", print_help=False)
def run(self, args, opts):
#settings = get_project_settings()
spider_loader = self.crawler_process.spider_loader
for spidername in args or spider_loader.list():
print "*********cralall spidername************" + spidername
self.crawler_process.crawl(spidername, **opts.spargs)
self.crawler_process.start()
self.crawler_process.spider_loader.list()方法獲取項目下全部的spider,而後利用self.crawler_process.crawl運行spider
三、commands命令下添加__init__.py文件
touch __init__.py
注意:這一步必定不能省略。
cnblogs.commands爲命令文件目錄,crawlall爲命令名。
4. 在settings.py中添加配置:
COMMANDS_MODULE = 'cnblogs.commands'
5. 運行命令scrapy crawlall
1九、scrapy中如何實現的記錄爬蟲的深度?
經過在settings.py中設置DEPTH_LIMIT的值能夠限制爬取深度,這個深度是與start_urls中定義url的相對值。cookie
20、scrapy中的pipelines工做原理?
pipelines文件實現了一個item pipieline類,和scrapy的item pipeline是同一個對象,
經過從settings中拿到咱們配置的REDIS_ITEMS_KEY做爲key,
把item串行化以後存入redis數據庫對應的value中(這個value能夠看出出是個list,咱們的每一個item是這個list中的一個結點),
這個pipeline把提取出的item存起來,主要是爲了方便咱們延後處理數據。併發
2一、scrapy的pipelines如何丟棄一個item對象?
//TODO
2二、簡述scrapy中爬蟲中間件和下載中間件的做用?
下載中間件:
下載中間件是處於引擎(crawler.engine)和下載器(crawler.engine.download())之間的一層組件,能夠有多個下載中間件被加載運行。
1.當引擎傳遞請求給下載器的過程當中,下載中間件能夠對請求進行處理 (例如增長http header信息,增長proxy信息等);
2.在下載器完成http請求,傳遞響應給引擎的過程當中, 下載中間件能夠對響應進行處理(例如進行gzip的解壓等)
Spider中間件(Middleware):
下載器中間件是介入到Scrapy的spider處理機制的鉤子框架,能夠添加代碼來處理髮送給 Spiders 的response及spider產生的item和request。
2三、scrapy-redis組件的做用?
實現分佈式抓取
2四、scrapy-redis組件中如何實現的任務的去重?
原理:
在分佈式爬取時,會有master機器和slave機器,其中,master爲核心服務器,slave爲具體的爬蟲服務器。
在master服務器上搭建一個redis數據庫,並將要抓取的url存放到redis數據庫中,全部的slave爬蟲服務器在抓取的時候從redis數據庫中獲取連接,
因爲scrapy_redis自身的隊列機制,slave獲取的url不會相互衝突,而後抓取的結果最後都存儲到數據庫中。
master的redis數據庫中還會將抓取過的url的指紋存儲起來,用來去重。相關代碼在dupefilter.py文件中的request_seen()方法中能夠找到。
去重問題:
dupefilter.py 裏面的源碼:
def request_seen(self, request):
fp = request_fingerprint(request)
added = self.server.sadd(self.key, fp)
return not added
去重是把 request 的 fingerprint 存在 redis 上,來實現的。
2五、scrapy-redis的調度器如何實現任務的深度優先和廣度優先?
//TODO
2六、假設有以下兩個list:a = ['a', 'b', 'c', 'd', 'e'],b = [1, 2, 3, 4, 5],
將 a 中的元素做爲 key,b 中元素做爲 value,將 a,b 合併爲字典。
a = ['a', 'b', 'c', 'd', 'e']
b = [1, 2, 3, 4, 5]
zip1 = zip(a,b)
# print(zip1) #<zip object at 0x000002984CB6CCC8>
# print(list(zip1))
d = {}
for i in zip1:
d[i[0]] = i[1]
print(d) #{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
2七、爬取數據後使用哪一個數據庫存儲數據的,爲何?
有規則的數據能夠存入 MySQL 中,可是要注意抓取內容出現缺失的狀況
不規則的數據存儲在 MongoDB 中,直接將數據存入再進行數據清洗