文章目錄
Scrapy框架
Scrapy框架整體架構
Scrapy 框架運行流程
Scrapy 框架各個模塊分析
-
引擎(Scrapy)
用來處理整個系統的數據流處理, 是整個框架的核心; -
調度器(Scheduler)
用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回,
即由調度器決定下一個所要爬取得網址是什麼,並且去重; -
下載器(Downloader)
用於下載網頁內容, 並將網頁內容返回給Spiders; -
爬蟲(Spiders)
負責爬取信息, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面 -
項目管道(Pipeline)
負責處理爬蟲從網頁中爬取的信息,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並經過幾個特定的次序處理數據。 -
下載器中間件(Downloader Middlewares)
位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。 -
爬蟲中間件(Spider Middlewares)
介於Scrapy引擎和爬蟲之間的框架,主要工作是處理蜘蛛的響應輸入和請求輸出。 -
調度中間件(Scheduler Middewares)
介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。
Scrapy基本工作流程
首先Spider將想要爬取的URL發給引擎,引擎將這些URL地址傳遞給Pipeline,Pipeline將URL排序,入隊之後交給Downloaders。Downloaders向互聯網發送請求,並接收下載響應(response),將響應經scrapyEngine,spiderMiddlewares(可選)交給spiders。
spiders處理response,提取數據並將數據經scrapyEngine交給pipline保存(可以是本地可以是數據庫)。提取的url重新經scrapyEngine交給scheduler進行下一個循環,直到無url請求時程序停止結束。
Scrapy常用命令
scrapy startproject 項目名稱
在當前目錄中創建一個項目文件(類似於Django)
scrapy genspider [-t template] <name> <domain>
創建爬蟲應用
scrapy crawl 爬蟲應用名稱 (-o 文件名)
單獨運行爬蟲(保存至文件中)
scrapy - redis 架構
scrapy - redis 簡介
scrapy-redis 是 scrapy 框架基於 redis 數據庫的組件,用於 scrapy 項目的分佈式開發和部署。
官方文檔:https://scrapy-redis.readthedocs.io/en/stable/
源碼位置:https://github.com/rmax/scrapy-redis
參考博客:https://www.cnblogs.com/kylinlin/p/5198233.html
Scrapy 即插即用組件
Scheduler 調度器 + Duplication 複製 過濾器, Item Pipeline ,基本spider。
scrapy - redis 架構
基本運行流程
首先 Slaver 端從 Master 端拿任務( Request 、 url )進行數據抓取, Slaver 抓取數據的同
時,產生新任務的 Request 便提交給 Master 處理;
Master 端只有一個 Redis 數據庫,負責將未處理的 Request 去重和任務分配,將處理後的
Request 加入待爬隊列,並且存儲爬取的數據。
Scrapy-Redis 默認使用的就是這種策略,實現簡單,因爲任務調度等工作 Scrapy-Redis 都已經幫我
們做好了,我們只需要繼承 RedisSpider 、指定 redis_key 就行了。
優缺點
-
優勢:
分佈式爬取
可以啓動多個 spider 工程,相互之間共享單個 redis 的 requests 隊列。最適合廣泛的多個域名網站的內容爬取。分佈式數據處理
爬取到的 scrapy 的 item 數據可以推入到 redis 隊列中,這意味着你可以根據需求啓動盡能多的處理程序來共享item的隊列,進行item數據持久化處理 -
缺點:
Scrapy-Redis 調度的任務是 Request 對象,裏面信息量比較大(不僅包含 url ,還有
callback 函數、 headers 等信息)降低爬蟲速度
佔用 Redis 大量的存儲空間
需要一定硬件水平
scrapy - redis 常用配置
# 使用了scrapy_redis的去重組件,在redis數據庫裏做去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用了scrapy_redis的調度器,在redis裏分配請求
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#
在redis中保持scrapy-redis用到的各個隊列,從而允許暫停和暫停後恢復,也就是不清理redis
queues
SCHEDULER_PERSIST = True
# 通過配置RedisPipeline將item寫入key爲 spider.name : items 的redis的list中,供後面的分
布式處理item 這個已經由 scrapy-redis 實現,不需要我們寫代碼,直接使用即可
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 100 ,
}
# 指定redis數據庫的連接參數
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
scrapy - redis 鍵名介紹
scrapy-redis 中都是用key-value形式存儲數據,其中有幾個常見的key-value形式
scrapy - redis 簡單實例
在原來非分佈式爬蟲的基礎上,使用 scrapy-redis 簡單搭建一個分佈式爬蟲,過程只需要修改下面文件:
settings.py
spider 文件
繼承類:由 scrapy.Spider 修改爲 RedisSpider
start_url 已經不需要了,修改爲: redis_key = “xxxxx”
在 redis 數據庫中,設置一個 redis_key 的值,作爲初始的 url , scrapy 就會自動在redis 中取出 redis_key 的值,作爲初始 url ,實現自動爬取。
lpush xxxx:start_urls http:xxxxx.com/xxxx
項目案例
項目介紹
爲了彙總、歸類和整合網絡上雜亂無章的職位信息,設計基於 Scrapy 的職位畫像系統,該系統將招聘
網站的招聘頁面進行劃分.利用 Python 使用 Xpath 和正則表達式的爬取規則設計網頁爬取器,獲得
職位信息.利用 MySQL 數據庫存儲爬取的數據,並進行數據清洗及分析,使用 Flask 和 Echarts 實
現數據可視化.該系統通過圖表直觀展現職位畫像,幫助用戶瞭解目前各個領域職位的需求情況,爲用
戶提供參考,同時從各個維度搭建職位檢索功能.
項目需求
數據來源: 拉鉤網, Boss直聘和 51job 網站
數據提取
Spider代碼
import scrapy
import requests
from ZhiWei import settings
from fake_useragent import UserAgent
class lagouSpider(scrapy.Spider):
name = 'lagou'
allowed_domains = ['lagou.com']
start_urls = ['http://lagou.com/']
def start_requests(self):
ua = UserAgent()
headers = {
'Host': 'www.lagou.com',
'Origin': 'https://www.lagou.com',
'Referer': 'https://www.lagou.com/jobs/list_python',
'Connection': 'keep-alive',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'User-Agent': ua.random
}
data = {
'first': 'false',
'pn': str(1),
'kd': 'python'
}
url_start = 'https://www.lagou.com/jobs/list_python'
url_prase = 'https://www.lagou.com/jobs/list_python/postionAjax.josn?needAddtionalResult = false'
session = requests.Session()
session.get(url_start, headers=headers, timeout=3)
cookies = session.cookies
yield scrapy.FormRequest(url_prase,
callback=self.parse,
method='POST',
formdata=data,
headers=headers,
cookies=dict(cookies))
def parse(self, response):
print(response.text)
import json
data = json.loads(response.text)
items
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class TutorialItem(scrapy.Item):
# define the fields for your item here like:
address = scrapy.Field()
salary = scrapy.Field()
create_time = scrapy.Field()
body = scrapy.Field()
company_name = scrapy.Field()
postion_id = scrapy.Field()
position_name = scrapy.Field()
work_year = scrapy.Field()
educational = scrapy.Field()
pass
class OtherItem(scrapy.Item):
name = scrapy.Field()
Pipeline
class ZhiweiPipeline(object):
def process_item(self,item,spider):
return item
setting
# -*- coding: utf-8 -*-
# Scrapy settings for ZhiWei project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
# https://docs.scrapy.org/en/latest/topics/settings.html
# https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
# https://docs.scrapy.org/en/latest/topics/spider-middleware.html
BOT_NAME = 'ZhiWei'
SPIDER_MODULES = ['ZhiWei.spiders']
NEWSPIDER_MODULE = 'ZhiWei.spiders'
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'ZhiWei (+http://www.yourdomain.com)'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32
# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16
# Disable cookies (enabled by default)
#COOKIES_ENABLED = False
# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False
# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
# 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
#}
# 使用了scrapy_redis的去重組件,在redis數據庫裏做去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用了scrapy_redis的調度器,在redis裏分配請求
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#在redis中保持scrapy-redis用到的各個隊列,從而允許暫停和暫停後恢復,也就是不清理redisqueues
SCHEDULER_PERSIST = True
# 通過配置RedisPipeline將item寫入key爲 spider.name : items 的redis的list中,供後面的分佈式處理item 這個已經由 scrapy-redis 實現,不需要我們寫代碼,直接使用即可
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 100 ,
'ZhiWei.pipelines.ZhiweiPipeline': 300,
}
# 指定redis數據庫的連接參數
REDIS_HOST = '127.0.0.1'
REDIS_PORT = 6379
# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
# 'ZhiWei.middlewares.ZhiweiSpiderMiddleware': 543,
#}
# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
# 'ZhiWei.middlewares.ZhiweiDownloaderMiddleware': 543,
#}
# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
# 'scrapy.extensions.telnet.TelnetConsole': None,
#}
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
# 'ZhiWei.pipelines.ZhiweiPipeline': 300,
#}
# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False
# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'