爬蟲————Scrapy框架和scrapy - redis 架構

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'

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