scrapy爬蟲框架
中文學習文檔:https://scrapy-chs.readthedocs.io/zh_CN/0.24/index.html
1、爬蟲框架有哪些:
- scrapy
- pyspider
- crawley
2、scrapy框架介紹
- https://doc.scrapy.org/en/latest/
- https://scrapy-chs.readthedocs.io/zh_CN/0.24/index.html
- http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html
3、安裝
(這裏安裝會遇到很多錯誤,這裏不再介紹,可以自己根據自己遇到的錯誤進行搜素解決方法)
4、scrapy包含的部件
- Engine:引擎負責控制系統所有組件之間的數據流,並在發生某些操作時觸發事件。
- Scheduler:調度程序接收來自引擎的請求,並將它們排入隊列,並在之後,當Engine需要的時候,將requests發送給engine。
- Downloader:下載器負責提取網頁並將它們饋送到引擎,然後引擎將其發送給spider。
- Spiders:蜘蛛是Scrapy用戶編寫的自定義類,用於解析響應並從中提取item項目(也稱爲抓取的項目)或追加的其他請求。(負責把下載器得到的網頁/結果進行分解,分解成數據+鏈接。)
- Item Pipeline:Item Pipeline負責處理被蜘蛛提取的item, 典型的任務包括清理,驗證和持久性(如將項目存儲在數據庫中)。 這一部分在上一篇文章中也詳細的介紹過了。
- Downloader middlewares:下載中間件,自定義下載的功能擴展組件。下載器中間件是位於引擎和下載器之間的特定的鉤子,當它們從引擎傳遞到下載器時處理請求,以及從下載器傳遞到引擎的響應。使用下載中間件可以達成如下的目的:
- 在將請求發送到下載器之前處理請求(即在Scrapy將請求發送到網站之前)。在傳遞給蜘蛛之前改變接收到的響應;在傳遞給蜘蛛之前改變接收到的響應;
- 發送新的請求,而不是將接收到的響應傳遞給蜘蛛;
- 發送新的請求,而不是將接收到的響應傳遞給蜘蛛;向蜘蛛傳遞響應而不需要獲取網頁;
- SpiderMiddleware爬蟲中間件(功能擴展組件):對spider進行功能擴展
5、爬蟲項目大概流程
- 新建項目:scrapy startproject xxx
- 明確需要目標/產出: 編寫item.py
- 製作爬蟲:地址 spider/xxspider.py
- 存儲內容:pipelines.py,
6、部件介紹
1、ItemPipeline
- 對應的是pipelines文件
- 爬蟲提取出數據存入item後,item中保存的數據需要進一步處理,比如清洗,去重,存儲等
- process_item:
- spider提取出來的item作爲參數傳入,同時傳入的還有spider
- 此方法必須實現
- 必須返回一個Item對象,被丟棄的item不會被之後的pipeline處理
- __init__:構造函數:進行一些必要的參數初始化
- open_spider(spider):spider對象被開啓的時候調用
- close_spider(spider):當spider對象被關閉的時候調用
2、Spider
- 對應的是文件夾spiders下的文件
- __init__: 初始化爬蟲名稱,start_urls列表
- start_requests:生成Requests對象交給Scrapy下載並返回response
- parse: 根據返回的response解析出相應的item,item自動進入pipeline; 如果需要,解析出url,url自動交給requests塊,一直循環下去
- start_request: 此方法僅能被調用一次,讀取start_urls內容並啓動循環過程
- name:設置爬蟲名稱
- start_urls: 設置開始第一批爬取的url
- allow_domains:spider允許爬去的域名列表
- start_request(self): 只被調用一次
- parse
- log:日誌記錄
3、中間件(DownloaderMiddlewares)
- 中間件是處於引擎和下載器中間的一層組件
- 可以有很多個,被按順序加載執行
- 作用是對發出的請求和返回的結果進行預處理
- 在middlewares文件中
- 需要在settings中設置以便生效
- 一般一箇中間件完成一項功能
- 必須實現以下一個或者多個方法
- process_request(self, request, spider)
- 在request通過的時候被調用
- 必須返回None或Response或Request或raise IgnoreRequest
- None: scrapy將繼續處理該request
- Request: scrapy會停止調用process_request並沖洗調度返回的reqeust
- Response: scrapy不會調用其他的process_request或者process_exception,直接講該response作爲結果返回
- 同時會調用process_response函數
- process_response(self, request, response, spider)
- 跟process_request大同小異
- 每次返回結果的時候會自動調用
- 可以有多個,按順序調用
- process_request(self, request, spider)
案例代碼:
import random
import base64
# 從settings設置文件中導入值
from settings import USER_AGENTS
from settings import PROXIES
# 隨機的 User-Agent
class RandomUserAgent(object):
def process_request(self, request, spider):
useragent = random.choice(USER_AGENTS)
request.headers.setdefault("User-Agent", useragent)
class RandomProxy(object):
def process_request(self, request, spider):
proxy = random.choice(PROXIES)
if proxy['user_passwd'] is None:
# 沒有代理賬戶驗證的代理使用方式
request.meta['proxy'] = "http://" + proxy['ip_port']
else:
# 對賬戶密碼進行 base64 編碼轉換
base64_userpasswd = base64.b64encode(proxy['user_passwd'])
# 對應到代理服務器的信令格式裏
request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd
request.meta['proxy'] = "http://" + proxy['ip_port']
7、設置settings的相關代碼
USER_AGENTS = [
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR
3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0;
SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET
CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR
2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko,
Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3)
Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-
Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0
Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5"
]
PROXIES = [
{'ip_port': '111.8.60.9:8123', 'user_passwd': 'user1:pass1'},
{'ip_port': '101.71.27.120:80', 'user_passwd': 'user2:pass2'},
{'ip_port': '122.96.59.104:80', 'user_passwd': 'user3:pass3'},
{'ip_port': '122.224.249.122:8088', 'user_passwd': 'user4:pass4'},
]
8、去重
- 爲了放置爬蟲陷入死循環,需要去重
- 即在spider中的parse函數中,返回Request的時候加上dont_filter=False參數
myspeder(scrapy.Spider):
def parse(.....):
......
yield scrapy.Request(url=url, callback=self.parse, dont_filter=False)
9、如何在scrapy使用selenium
- 可以放入中間件中的process_request函數中
- 在函數中調用selenium,完成爬取後返回Response
calss MyMiddleWare(object):
def process_request(.....):
driver = webdriver.Chrome()
html = driver.page_source
driver.quit()
return HtmlResponse(url=request.url, encoding='utf-8', body=html, request=request)