## scrapy 依賴 twisted
- twisted 是一個基於事件循環的 異步非阻塞 框架/模塊cookie
## 項目的建立 框架
1. 建立 project scrapy startproject 項目名稱 項目名稱(項目結構) - spiders # 爬蟲文件 - q.py - w.py - items.py # 持久化 - pipelines # 持久化 - middlewares.py # 中間件 - settings.py # 配置文件(爬蟲) scrapy.cfg # 配置文件(部署) 2. 建立爬蟲 cd 項目名稱 scrapy genspider q q.com scrapy genspider w w.com 3. 啓動爬蟲 scrapy crawl q --nolog # 不查看日誌 scrapy crawl w # 默認查看日誌
## pipeline 作持久化異步
- pipeline 是全部爬蟲公用的,若是想要給某個爬蟲制定須要使用 spider 參數進行判斷處理:
if spider.name == 'xxx'scrapy
1. 自定義的爬蟲文件中 將每次獲取到的數據 傳給 ScrapyDeom1Item 類方法 for item in item_list: href = item.xpath('.//a/@href').extract_first() txt = item.xpath('.//a/text()').extract_first() yield ScrapyDeom1Item(text=txt, href=href) 2. items 中 ScrapyDeom1Item 類方法 將須要存儲的數據接收到。 class ScrapyDeom1Item(scrapy.Item): href = scrapy.Field() text = scrapy.Field() 3. settings 中定義作持久化的類( ScrapyDeom1Pipeline ) 和 定義一個文件路徑 ITEM_PIPELINES = { 'scrapy_deom1.pipelines.ScrapyDeom1Pipeline': 300, # 文件路徑 # 優先級( 1-1000 ) } PATH = 'new.log' 4. 到 pipelines.py 文件中 找到 ScrapyDeom1Pipeline 類並作持久化 from scrapy.exceptions import DropItem class ScrapyDeom1Pipeline(object): def __init__(self, path): # 初始化定義文件操做 和 文件要保存的路徑 self.f = None self.path = path @classmethod def from_crawler(cls, crawler): """ 初始化的時候,用來建立 pipeline 對象 :param crawler: :return: """ # 去settings 尋找要保存的文件路徑 path = crawler.settings.get('PATH') return cls(path) def open_spider(self, spider): """ 爬蟲剛啓動時調用 - 此處用來作打開文件操做 :param spider: :return: """ self.f = open(self.path, 'a+') def process_item(self, item, spider): """ 爬蟲執行中調用 - 此處用來作將數據寫入文件 操做 :param item: :param spider: :return: """ self.f.write(item['href']+'\n') # raise DropItem() # 拋出異常,使後續的 pipeline 的 process_item 方法不執行 return item # 這個 item 是要返回給下個類的 def close_spider(self, spider): """ 爬蟲執行完畢後調用 - 此處用來作關閉文件操做 :param spider: :return: """ self.f.close()
## 去重 ide
1. 建立一個 dupefilters.py 文件(用於作去重操做): from scrapy.dupefilters import BaseDupeFilter from scrapy.utils.request import request_fingerprint class MyDupeFilter(BaseDupeFilter): def __init__(self): self.visited_fd = set() @classmethod def from_settings(cls, settings): return cls() def request_seen(self, request): """ 判斷當前請求的URL是否存在 - 用於去重 - 若是存在則 pass - 如不存在則 添加 :param request: :return: """ # 將當前 URL 加密成必定位數的字符 print(request) fd = request_fingerprint(request=request) if fd in self.visited_fd: return True self.visited_fd.add(fd) def open(self): # can return deferred """ 執行前的一些操做 :return: """ print('爬蟲開始') def close(self, reason): # can return a deferred """ 執行結束後的一些操做 :param reason: :return: """ print('爬蟲結束') def log(self, request, spider): # log that a request has been filtered """ 訪問的每個 URL 的日誌信息 :param request: :param spider: :return: """ pass 2. settings 中註冊這個類 DUPEFILTER_CLASS = 'scrapy_demo1.dupefilters.MyDupeFilter' 3. 能夠設置是否使用當前定義的去重方法 # True 表示不使用 # False 表示使用 (默認爲False) yield Request(url=page, callback=self.parse, dont_filter=True)
## 限制深度查詢加密
配置文件中(settings): DEPTH_LIMIT = 3 # 查詢深度設置爲三層
## Cookieurl
# 解析 cookie
cookie_jar = CookieJar()
cookie_jar.extract_cookies(response, response.request)
# 去對象中將cookie解析到字典
for k, v in cookie_jar._cookies.items():
for i, j in v.items():
for m, n in j.items():
self.cookie_dict[m] = n.value
# 獲取 cookie
cookies=self.cookie_dict,