爬虫基础之Scrapy框架架构

目录

 

Scrapy框架

Scrapy框架介绍:

Scrapy架构图(Scrapy 使用了 Twisted异步网络库来处理网络通讯):

Scrapy框架模块功能:

Scrapy运行流程大概如下:

安装和文档:

快速入门:

创建项目:

目录结构介绍:

spiders包:以后所有的爬虫,都是存放到这个里面。

使用Scrapy框架爬取糗事百科段子项目 

 

糗事百科Scrapy爬虫项目

总结:

CrawlSpider

 

创建CrawlSpider爬虫:

LinkExtractors链接提取器:

Rule规则类:

微信小程序社区CrawlSpider案例

总结:

Scrapy Shell

打开Scrapy Shell:

总结:

Request和Response对象

Request对象:

Response对象:

发送POST请求:

模拟登录

案例一:模拟登录人人网

案例二:模拟登录豆瓣网(识别验证码)

下载文件和图片

为什么要选择使用scrapy内置的下载文件的方法

下载文件的 Files Pipeline:

下载图片的Images Pipeline:

汽车之家宝马5系高清图片下载实战

下载中间件

Downloader Middlewares (下载器中间件)

process_request(self, request, spider)

process_response(self, request, response, spider)

随机请求头中间件:      

ip代理池中间件

Scrapy爬虫实战

Boss直聘爬虫。

简书网站整站爬虫。

 

Scrapy-Redis分布式组件

redis数据库介绍:

概述

redis使用场景:

redis和memcached的比较:

redis在ubuntu系统中的安装与启动

redis在windows系统中的安装与启动:

其他机器访问本机redis服务器:

对redis的操作

 

Scrapy-Redis分布式爬虫组件

分布式爬虫的优点:

分布式爬虫必须要解决的问题:

安装:

Scrapy-Redis架构:

编写Scrapy-Redis分布式爬虫:

搜房网分布式爬虫项目


Scrapy框架

Scrapy框架介绍:

写一个爬虫,需要做很多的事情。比如:发送网络请求、数据解析、数据存储、反反爬虫机制(更换ip代理、设置请求头等)、异步请求等。这些工作如果每次都要自己从零开始写的话,比较浪费时间。因此Scrapy把一些基础的东西封装好了,在他上面写爬虫可以变的更加的高效(爬取效率和开发效率)。因此真正在公司里,一些上了量的爬虫,都是使用Scrapy框架来解决。

Scrapy架构图(Scrapy 使用了 Twisted异步网络库来处理网络通讯):

流程图(1):


流程图(2):

Scrapy框架模块功能:

 

  • 引擎(Scrapy)
    用来处理整个系统的数据流, 触发事务(框架核心)
  • 调度器(Scheduler)
    用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
  • 下载器(Downloader)
    用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
  • 爬虫(Spiders)
    爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
  • 项目管道(Pipeline)
    负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
  • 下载器中间件(Downloader Middlewares)
    位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
  • 爬虫中间件(Spider Middlewares)
    介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
  • 调度中间件(Scheduler Middewares)
    介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

Scrapy运行流程大概如下:

  1. 引擎从调度器中取出一个链接(URL)用于接下来的抓取
  2. 引擎把URL封装成一个请求(Request)传给下载器
  3. 下载器把资源下载下来,并封装成应答包(Response)
  4. 爬虫解析Response
  5. 解析出实体(Item),则交给实体管道进行进一步的处理
  6. 解析出的是链接(URL),则把URL交给调度器等待抓取

安装和文档:

  1. 安装:通过pip install scrapy即可安装。
  2. Scrapy官方文档:http://doc.scrapy.org/en/latest
  3. Scrapy中文文档:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html

注意:

  1. ubuntu上安装scrapy之前,需要先安装以下依赖:
    sudo apt-get install python3-dev build-essential python3-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev,然后再通过pip install scrapy安装。
  2. 如果在windows系统下,提示这个错误ModuleNotFoundError: No module named 'win32api',那么使用以下命令可以解决:pip install pypiwin32

快速入门:

创建项目:

要使用Scrapy框架创建项目,需要通过命令来创建。首先进入到你想把这个项目存放的目录。然后使用以下命令创建:

scrapy startproject [项目名称]

目录结构介绍:


以下介绍下主要文件的作用:

  1. items.py:用来存放爬虫爬取下来数据的模型。
  2. middlewares.py:用来存放各种中间件的文件。
  3. pipelines.py:用来将items的模型存储到本地磁盘中。
  4. settings.py:爬虫的一些配置信息(比如请求头、多久发送一次请求、ip代理池等)。
  5. scrapy.cfg:项目的配置文件。
  6. spiders包:以后所有的爬虫,都是存放到这个里面。

使用Scrapy框架爬取糗事百科段子项目 

 

使用命令创建一个爬虫:

scrapy genspider qsbk "qiushibaike.com"

创建了一个名字叫做qsbk的爬虫,并且能爬取的网页只会限制在qiushibaike.com这个域名下。

爬虫代码解析:

import scrapy

class QsbkSpider(scrapy.Spider):
    name = 'qsbk'
    allowed_domains = ['qiushibaike.com']
    start_urls = ['http://qiushibaike.com/']

    def parse(self, response):
        pass

其实这些代码我们完全可以自己手动去写,而不用命令。只不过是不用命令,自己写这些代码比较麻烦。
要创建一个Spider,那么必须自定义一个类,继承自scrapy.Spider,然后在这个类中定义三个属性和一个方法。

  1. name:这个爬虫的名字,名字必须是唯一的。
  2. allow_domains:允许的域名。爬虫只会爬取这个域名下的网页,其他不是这个域名下的网页会被自动忽略。
  3. start_urls:爬虫从这个变量中的url开始。
  4. parse:引擎会把下载器下载回来的数据扔给爬虫解析,爬虫再把数据传给这个parse方法。这个是个固定的写法。这个方法的作用有两个,第一个是提取想要的数据。第二个是生成下一个请求的url。

修改settings.py代码:

在做一个爬虫之前,一定要记得修改setttings.py中的设置。两个地方是强烈建议设置的。

  1. ROBOTSTXT_OBEY设置为False。默认是True。即遵守机器协议,那么在爬虫的时候,scrapy首先去找robots.txt文件,如果没有找到。则直接停止爬取。
  2. DEFAULT_REQUEST_HEADERS添加User-Agent。这个也是告诉服务器,我这个请求是一个正常的请求,不是一个爬虫。

完成的爬虫代码:

  1. 爬虫部分代码:

     import scrapy
     from abcspider.items import QsbkItem
    
     class QsbkSpider(scrapy.Spider):
         name = 'qsbk'
         allowed_domains = ['qiushibaike.com']
         start_urls = ['https://www.qiushibaike.com/text/']
    
         def parse(self, response):
             outerbox = response.xpath("//div[@id='content-left']/div")
             items = []
             for box in outerbox:
                 author = box.xpath(".//div[contains(@class,'author')]//h2/text()").extract_first().strip()
                 content = box.xpath(".//div[@class='content']/span/text()").extract_first().strip()
                 item = QsbkItem()
                 item["author"] = author
                 item["content"] = content
                 items.append(item)
             return items
    
  2. items.py部分代码:

     import scrapy
     class QsbkItem(scrapy.Item):
         author = scrapy.Field()
         content = scrapy.Field()
    
  3. pipeline部分代码:

     import json
    
     class AbcspiderPipeline(object):
         def __init__(self):
    
             self.items = []
    
         def process_item(self, item, spider):
             self.items.append(dict(item))
             print("="*40)
             return item
    
         def close_spider(self,spider):
             with open('qsbk.json','w',encoding='utf-8') as fp:
                 json.dump(self.items,fp,ensure_ascii=False)
    

settings.py中要把 ITEM_PIPELINES 打开

'qsbk.pipelines.QsbkPipeline': 300, #300代表pipeline的优先级,值越小,优先级越高

运行scrapy项目:

运行scrapy项目。需要在终端,进入项目所在的路径,然后scrapy crawl [爬虫名字]即可运行指定的爬虫。如果不想每次都在命令行中运行,那么可以把这个命令写在一个文件中。以后就在pycharm中执行运行这个文件就可以了。比如现在工程的根目录新创建一个文件叫做start.py,然后在这个文件中填入以下代码:

from scrapy import cmdline

cmdline.execute("scrapy crawl qsbk".split())

糗事百科Scrapy爬虫项目

总结:

一、创建项目和爬虫:

  1.  创建项目:‘scrapy startproject [爬虫名字]’。
  2. 创建爬虫:进入到项目 所在的路径,执行命令:`scrapy genspider [ 爬虫名字] [ 爬虫的域名]`。注意,爬虫名字不能和项目名一样。

二、糗事百科Scrapy爬虫笔记:

  1. responst是一个`scrapy.http.response.html.HtmlResponse`对象。可以执行`xpath`和`css`语法来提取数据。
  2. 提取出来的数据,是一个`Selector`或者是一个`SelectorList`对象。如果想要获取其中的字符串,那么应该 执行`getall`或者`get`方法。
  3. getall方法:获取`Selector`中的所有文本。返回的是一个列表。等同于extract方法。
  4. get方法:获取的是`Selector`中的第一个文本。返回的是一个str类型。等同于extract_first方法。
  5. 如果数据解析回来,要传给pipline处理。那么可以使用`yield`来返回 。或者是收集所有的item,最后统一使用return返回。
  6. item:建议在`items.py`中定义好模型,以后就不要使用字典。
  7. pipeline:这个是专门用来保存数据的。其中有三个方法是会经常用的。

          *`open_spider(self,spider)`:当爬虫被打开的时候执行。

          *`process_item(self,item,spider)`:当爬虫有item传过来的时候会被调用,一般用来保存数据。           

          *`close_spider(self,spider)`:当爬虫关闭的时候会被调用。

           要激活piplilne,应该在`settings.py`中,设置`ITEM_PIPELINES`示例如下:

ITEM_PIPELINES = {
   'qsbk.pipelines.QsbkPipeline': 300,
}

 

CrawlSpider

在上一个糗事百科的爬虫案例中。我们是自己在解析完整个页面后获取下一页的url,然后重新发送一个请求。有时候我们想要这样做,只要满足某个条件的url,都给我进行爬取。那么这时候我们就可以通过CrawlSpider来帮我们完成了。CrawlSpider继承自Spider,只不过是在之前的基础之上增加了新的功能,可以定义爬取的url的规则,以后scrapy碰到满足条件的url都进行爬取,而不用手动的yield Request

 

创建CrawlSpider爬虫:

之前创建爬虫的方式是通过scrapy genspider [爬虫名字] [域名]的方式创建的。如果想要创建CrawlSpider爬虫,那么应该通过以下命令创建:

scrapy genspider -t crawl [爬虫名字] [域名]

LinkExtractors链接提取器:

使用LinkExtractors可以不用程序员自己提取想要的url,然后发送请求。这些工作都可以交给LinkExtractors,他会在所有爬的页面中找到满足规则的url,实现自动的爬取。以下对LinkExtractors类做一个简单的介绍:

class scrapy.linkextractors.LinkExtractor(
    allow = (),
    deny = (),
    allow_domains = (),
    deny_domains = (),
    deny_extensions = None,
    restrict_xpaths = (),
    tags = ('a','area'),
    attrs = ('href'),
    canonicalize = True,
    unique = True,
    process_value = None
)

主要参数讲解:

  • allow:允许的url。所有满足这个正则表达式的url都会被提取。
  • deny:禁止的url。所有满足这个正则表达式的url都不会被提取。
  • allow_domains:允许的域名。只有在这个里面指定的域名的url才会被提取。
  • deny_domains:禁止的域名。所有在这个里面指定的域名的url都不会被提取。
  • restrict_xpaths:严格的xpath。和allow共同过滤链接。

Rule规则类:

定义爬虫的规则类。以下对这个类做一个简单的介绍:

class scrapy.spiders.Rule(
    link_extractor, 
    callback = None, 
    cb_kwargs = None, 
    follow = None, 
    process_links = None, 
    process_request = None
)

主要参数讲解:

  • link_extractor:一个LinkExtractor对象,用于定义爬取规则。
  • callback:满足这个规则的url,应该要执行哪个回调函数。因为CrawlSpider使用了parse作为回调函数,因此不要覆盖parse作为回调函数自己的回调函数。
  • follow:指定根据该规则从response中提取的链接是否需要跟进。
  • process_links:从link_extractor中获取到链接后会传递给这个函数,用来过滤不需要爬取的链接。

微信小程序社区CrawlSpider案例

总结:

 需要使用`LinkExtractor`和`Rule`。这两个东西决定爬虫的具体走向。

  1. allow设置规则的方法:要能够限制在我们想要的url上面。不要跟其它url产生相同的正则表达式即可。
  2. 什么情况下使用follow:如果在爬取页面的时候,需要进满足当前条件的url再进行跟进,那么就设置为True。否则设置为Fash。
  3. 什么情况下该指定callback:如果这个url对应的页面,只是为了获取更多的url,并不需要里面的数据,那么可以不指定callback。如果想要获取url对应页面中的数据,那么就需要指定一个callback。

 

Scrapy Shell

我们想要在爬虫中使用xpath、beautifulsoup、正则表达式、css选择器等来提取想要的数据。但是因为scrapy是一个比较重的框架。每次运行起来都要等待一段时间。因此要去验证我们写的提取规则是否正确,是一个比较麻烦的事情。因此Scrapy提供了一个shell,用来方便的测试规则。当然也不仅仅局限于这一个功能。

打开Scrapy Shell:

打开终端,进入到Scrapy项目所在的目录,然后进入到scrapy框架所在的虚拟环境中,输入命令scrapy shell [链接]。就会进入到scrapy的shell环境中。在这个环境中,你可以跟在爬虫的parse方法中一样使用了。 

总结:

  1. 可以方便我们做一些数据提取的测试代码。
  2. 如果想要执行scrapy命令,那么毫无疑问,肯定是要先进入到scrapy所在的环境中。
  3. 如果想要读取某个项目的配置信息,那么应该先进入到这个项目中,再执行`scrapy shell`命令。

Request和Response对象

Request对象:

Request对象在我们写爬虫,爬取一页的数据需要重新发送一个请求的时候调用。这个类需要传递一些参数,其中比较常用的参数有

  1. url:这个request对象发送请求url。
  2. callback:在下载器下载完相应的数据后执行的回调函数。
  3. method:请求的方法。默认为GET方法,可以设置为其他方法。
  4. headers:请求头,对于一些固定的设置,放在settings.py中指定就可以了。对于那些非固定的,可以在发送请求的时候指定。
  5. meta:比较常用。用于在不同的请求之间 传递数据用的。
  6. encoding:编码。默认的为utf-8,使用默认的就可以了。
  7. dot_filter:表示不由调度器过滤。在执行多次重复的请求的时候用得比较多。
  8. errback:在发生错误的时候执行的函数。

Response对象:

Response对象一般是由Scrapy给你自动构建的。因些开发者不需要关心如何创建Response对象,而是如何使用他。Response对象有

很多属性,可以用来提取数据的。主要有以下属性:

  1. meta:从其他请求传过来的meta属性,可以用来保持多个请求之间 的数据连接。
  2. encoding:返回当前字符串编码和解码的格式。
  3. text:将返回来的数据作为unicode字符串返回。
  4. body:将返回来的数据作为bytes字符串返回。
  5. xpath:xpath选择器。
  6. css:css选择器。

发送POST请求:

有时候我们想在在请求数据的时候发送post请求,那么这时候需要使用Request的子类FormRequest来实现。如果想要在爬虫一开始

的时候就发送POST请求,那么需要在爬虫类中重写start_requests(delf)方法,并且不再调用 start_urls里的url。

模拟登录

案例一:模拟登录人人网

1、想要发送post请求,那么推荐使用`scrpay.FormRequest`方法。可以方便的指定表单数据。

2、如果想在爬虫一开始的时候就发送post请求,那么应该重写`start_requests`方法。在这个方法中,发送post请求。

案例二:模拟登录豆瓣网(识别验证码)

待完善

 

下载文件和图片

Scrapy为下载item中包含的文件(比如在攫取到产品时,同时也想保存对应的图片)提供了一个可重用的item pipelinses.

这些pipeline有些共同的方法和结构(我们称之为media pipeline)。一般来说你会使用Files Pipeline或者Images Pipelines。

为什么要选择使用scrapy内置的下载文件的方法

  1. 避免重新下载最近已经下载过的数据。
  2. 可以方便的指定文件存储的路径。
  3. 可以将下载的图片转换成通用的格式,比如png或者jpg.
  4. 可以方便生成缩略图。
  5. 可以方便的检测图片的宽和高,确保他们满足最小限制。
  6. 异步下载,效率非常高。

下载文件的 Files Pipeline:

当使用Files Pipeline 下载文件的时候,按照以下步骤来完成:

  1. 定义好一个Item,然后在这个item中定义两个属性,分别为file_urls以及files。file_urls是用来存储需要下载的图片的url链接,需要给一个列表。
  2. 当文件下载完成后,会把文件下载的相关信息存储到item的files属性中。比如下载路径、下载的url和文件的验证码等。
  3. 在配置文件settings.py中配置FILES_STORE,这个配置是用来设置文件下载下来的路径。
  4. 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.files.FilesPipeline:1。

下载图片的Images Pipeline:

当使用Images Pipeline下载图片的时候,按照以下步骤来完成:

 

  1. 定义好一个Item,然后在这个item中定义两个属性,分别为image_urls以及images。image_urls是用来存储需要下载的图片链接,需要给一个列表。
  2. 当文件下载完成后,会把文件下载的相关信息存储到item的images属性中。比如下载路径、下载的url和图片的验证码等。
  3. 在配置文件settings.py中配置IMAGES_STORE,这个配置是用来设置文件下载下来的路径。
  4. 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline:1。

 

汽车之家宝马5系高清图片下载实战

 

下载中间件

Downloader Middlewares (下载器中间件)

下载器中间件是引擎和下载器之间通信的中间件。在这个中间件中我们可以设置代理、更换请求头等来达到反反爬虫的目的,要写下载器中间件,可以在下载器中实现两个方法。一个是process_request(self, request, spider),这个方法会在请求发送之前执行,还有一个是process_response(self, request, response, spider),这个方法是数据下载到引擎之间执行。

 

process_request(self, request, spider)

这个方法是下载器在发送请求之前会执行的。一般可以在这里面设置随机代理ip等。

1、参数:

            。request:发送请求的request对象。

            。 spider:发送请求的spider对象。

2、返回值:

             。 返回None:如果返回None,Scrapy将继续处理该request,执行其它 中间件中的相应方法,直到合适的下载器处理函数被调用。

             。返回Response对象:Scrapy将不会调用任何其他的process_request方法,将直接返回response对象,已经激活中间件的process_response()方法则会在每个response返回时被调用。

             。返回Request对象:不再使用之前的request对象去下载数据,而是根据现在返回的request对象返回数据。

             。如果这个方法中抛出了异常,则会调用process_exception方法。      

 

process_response(self, request, response, spider)

这个方法是下载器在发送请求之前会执行的。一般可以在这里面设置随机代理ip等。

1、参数:

            。request:request对象。

            。 response:被处理的response对象。

            。spider:spider对象。

2、返回值:

             。 返回Response:会将这个新的response对象传给其他中间件,最终传给爬虫。

             。返回Response对象:下载器链接切断,返回response会重新被下载器调度下载。

             。如果抛出一个异常,那么调用response的errback方法,如果没有指定这个方法,那么会抛出一个异常。

 

随机请求头中间件:      

           爬虫在频繁访问一个页面的时候,这个请求头如果一直保持一致。那么很容易被服务器发现,从面禁止掉这个请求头的访问,因此我们要在访问这个页面之前随机的更改请求头,这样才可以避免爬虫被抓。随机更改请求头,可以在下载器中间件中实现,在请求发送给服务器之前,随机选择一个请求头。这样就可以避免总傅一个请求头了。示例代码如下:

class UserAgentDownloadMiddleware(object):
    USER_AGENTS = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; Browzar)',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; MyIE2; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0)'
    ]

    def process_request(self, request, spider):
        user_agent = random.choice(self.USER_AGENTS)
        request.headers['User-Agent'] = user_agent

user-agent列表网址:http://useragentstring.com/pages/useragentstring.php?typ=Browser

ip代理池中间件

购买代理:

在以下代理商中购买代理:

  1. 芝麻代理:http://www.zhimaruanjian.com/
  2. 太阳代理:http://www.taiyangruanjian.com/
  3. 快代理    :https://www.kuaidaili.com/
  4. 蚂蚁代理:http://www.mayidaili.com/

等购买代理。

使用ip代理池:

示例代码如下:

# 开放代理池设置
# class IPProxyDownloadMiddleware(object):
#     PROXIES = [
#         '171.41.81.164:9999',
#         '171.41.81.253:9999',
#         '171.41.81.96:9999',
#         '171.41.81.93:9999',
#         '112.85.171.65:9999',
#         '117.114.149.66:53281'
#         '106.12.217.43:8118'
#
#     ]
#
#     def process_request(self, request, spider):
#         proxy = random.choice(self.PROXIES)
#         request.meta['proxy'] = "http://" + proxy

# 独享代理池设置
class IPProxyDownloadMiddleware(object):

    def process_request(self, request, spider):
        proxy = '121.199.6.124:16816'
        user_password = "970138074:rcdj35ur"
        request.meta['proxy'] = "http://" + proxy
        # bytes
        b64_user_password = base64.b64encode(user_password.encode('utf-8'))
        request.headers['Proxy-Authorization'] = 'Basic' + b64_user_password.decode('utf-8')

完整代码示例

 

Scrapy爬虫实战

Boss直聘爬虫。

      Boss直聘有很高的反爬虫机制,只要用同一个ip访问多个职位列表页,就会被封掉ip。采用代理ip方式可以解决问题。

简书网站整站爬虫。

  1. 数据保存到mysql数据库中。
  2. 将selenium+chromedriver集成到scrapy.

 

 

 

Scrapy-Redis分布式组件

redis数据库介绍

概述

redis是一种支持分布式的nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(string,list列表[队列和栈],set[集合],sorted set[有序集合],hash(hash表))。相关参考文档:http://redisdoc.com/index.html

redis使用场景:

  1. 登录会话存储:存储在redis中,与memcached相比,数据不会丢失。
  2. 排行版/计数器:比如一些秀场类的项目,经常会有一些前多少名的主播排名。还有一些文章阅读量的技术,或者新浪微博的点赞数等。
  3. 作为消息队列:比如celery就是使用redis作为中间人。
  4. 当前在线人数:还是之前的秀场例子,会显示当前系统有多少在线人数。
  5. 一些常用的数据缓存:比如我们的BBS论坛,板块不会经常变化的,但是每次访问首页都要从mysql中获取,可以在redis中缓存起来,不用每次请求数据库。
  6. 把前200篇文章缓存或者评论缓存:一般用户浏览网站,只会浏览前面一部分文章或者评论,那么可以把前面200篇文章和对应的评论缓存起来。用户访问超过的,就访问数据库,并且以后文章超过200篇,则把之前的文章删除。
  7. 好友关系:微博的好友关系使用redis实现。
  8. 发布和订阅功能:可以用来做聊天软件。

redismemcached的比较:

 memcachedredis
类型纯内存数据库内存磁盘同步数据库
数据类型在定义value时就要固定数据类型不需要
虚拟内存不支持支持
过期策略支持支持
存储数据安全不支持可以将数据同步到dump.db中
灾难恢复不支持可以将磁盘中的数据恢复到内存中
分布式支持主从同步
订阅与发布不支持支持

redisubuntu系统中的安装与启动

  1. 安装:
     sudo apt-get install redis-server
    
  2. 卸载:
     sudo apt-get purge --auto-remove redis-server
    
  3. 启动:redis安装后,默认会自动启动,可以通过以下命令查看:

     ps aux|grep redis
    

    如果想自己手动启动,可以通过以下命令进行启动:

     sudo service redis-server start
    
  4. 停止:

     sudo service redis-server stop
    

redis在windows系统中的安装与启动:

  1. 下载:redis官方是不支持windows操作系统的。但是微软的开源部门将redis移植到了windows上。因此下载地址不是在redis官网上。而是在github上:https://github.com/MicrosoftArchive/redis/releases。
  2. 安装:点击一顿下一步安装就可以了。
  3. 运行:进入到redis安装所在的路径然后执行redis-server.exe redis.windows.conf就可以运行了。
  4. 连接:redismysql以及mongo是一样的,都提供了一个客户端进行连接。输入命令redis-cli(前提是redis安装路径已经加入到环境变量中了)就可以连接到redis服务器了。

其他机器访问本机redis服务器:

想要让其他机器访问本机的redis服务器。那么要修改redis.conf的配置文件,将bind改成bind [自己的ip地址或者0.0.0.0],其他机器才能访问。
注意:bind绑定的是本机网卡的ip地址,而不是想让其他机器连接的ip地址。如果有多块网卡,那么可以绑定多个网卡的ip地址。如果绑定到额是0.0.0.0,那么意味着其他机器可以通过本机所有的ip地址进行访问。

redis的操作

redis的操作可以用两种方式,第一种方式采用redis-cli,第二种方式采用编程语言,比如PythonPHPJAVA等。

  1. 使用redis-cliredis进行字符串操作:

  2. 启动redis

      sudo service redis-server start
    
  3. 连接上redis-server
      redis-cli -h [ip] -p [端口]
    
  4. 添加:

      set key value
      如:
      set username xiaotuo
    

    将字符串值value关联到key。如果key已经持有其他值,set命令就覆写旧值,无视其类型。并且默认的过期时间是永久,即永远不会过期。

  5. 删除:

      del key
      如:
      del username
    
  6. 设置过期时间:

      expire key timeout(单位为秒)
    

    也可以在设置值的时候,一同指定过期时间:

      set key value EX timeout
      或:
      setex key timeout value
    
  7. 查看过期时间:

      ttl key
      如:
      ttl username
    
  8. 查看当前redis中的所有key

      keys *
    
  9. 列表操作:

    • 在列表左边添加元素:

        lpush key value
      

      将值value插入到列表key的表头。如果key不存在,一个空列表会被创建并执行lpush操作。当key存在但不是列表类型时,将返回一个错误。

    • 在列表右边添加元素:

        rpush key value
      

      将值value插入到列表key的表尾。如果key不存在,一个空列表会被创建并执行RPUSH操作。当key存在但不是列表类型时,返回一个错误。

    • 查看列表中的元素:

        lrange key start stop
      

      返回列表key中指定区间内的元素,区间以偏移量startstop指定,如果要左边的第一个到最后的一个lrange key 0 -1

    • 移除列表中的元素:

      • 移除并返回列表key的头元素:
          lpop key
        
      • 移除并返回列表的尾元素:
        rpop key
        
      • 移除并返回列表key的中间元素:

          lrem key count value
        

        将删除key这个列表中,count个值为value的元素。

    • 指定返回第几个元素:

        lindex key index
      

      将返回key这个列表中,索引为index的这个元素。

    • 获取列表中的元素个数:

        llen key
        如:
        llen languages
      
    • 删除指定的元素:

        lrem key count value
        如:
        lrem languages 0 php
      

      根据参数 count 的值,移除列表中与参数 value 相等的元素。count的值可以是以下几种:

      • count > 0:从表头开始向表尾搜索,移除与value相等的元素,数量为count
      • count < 0:从表尾开始向表头搜索,移除与 value相等的元素,数量为count的绝对值。
      • count = 0:移除表中所有与value 相等的值。
  10. set集合的操作:

    • 添加元素:
        sadd set value1 value2....
        如:
        sadd team xiaotuo datuo
      
    • 查看元素:
        smembers set
        如:
        smembers team
      
    • 移除元素:
        srem set member...
        如:
        srem team xiaotuo datuo
      
    • 查看集合中的元素个数:
        scard set
        如:
        scard team1
      
    • 获取多个集合的交集:
        sinter set1 set2
        如:
        sinter team1 team2
      
    • 获取多个集合的并集:
        sunion set1 set2
        如:
        sunion team1 team2
      
    • 获取多个集合的差集:
      sdiff set1 set2
      如:
      sdiff team1 team2
      
  11. hash哈希操作:

    • 添加一个新值:

        hset key field value
        如:
        hset website baidu baidu.com
      

      将哈希表key中的域field的值设为value
      如果key不存在,一个新的哈希表被创建并进行 HSET操作。如果域 field已经存在于哈希表中,旧值将被覆盖。

    • 获取哈希中的field对应的值:

        hget key field
        如:
        hget website baidu
      
    • 删除field中的某个field

        hdel key field
        如:
        hdel website baidu
      
    • 获取某个哈希中所有的fieldvalue

        hgetall key
        如:
        hgetall website
      
    • 获取某个哈希中所有的field

        hkeys key
        如:
        hkeys website
      
    • 获取某个哈希中所有的值:

      hvals key
      如:
      hvals website
      
    • 判断哈希中是否存在某个field

      hexists key field
      如:
      hexists website baidu
      
    • 获取哈希中总共的键值对:

      hlen field
      如:
      hlen website
      
  12. 事务操作:Redis事务可以一次执行多个命令,事务具有以下特征:

    • 隔离操作:事务中的所有命令都会序列化、按顺序地执行,不会被其他命令打扰。
    • 原子操作:事务中的命令要么全部被执行,要么全部都不执行。
    • 开启一个事务:

        multi
      

      以后执行的所有命令,都在这个事务中执行的。

    • 执行事务:

        exec
      

      会将在multiexec中的操作一并提交。

    • 取消事务:

        discard
      

      会将multi后的所有命令取消。

    • 监视一个或者多个key

        watch key...
      

      监视一个(或多个)key,如果在事务执行之前这个(或这些) key被其他命令所改动,那么事务将被打断。

    • 取消所有key的监视:

        unwatch
      
  13. 发布/订阅操作:

    • 给某个频道发布消息:
        publish channel message
      
    • 订阅某个频道的消息:
        subscribe channel

 

Scrapy-Redis分布式爬虫组件

Scrapy是一个框架,他本身是不支持分布式的。如果我们想要做分布式的爬虫,就需要借助一个组件叫做Scrapy-Redis,这个组件正是利用了Redis可以分布式的功能,集成到Scrapy框架中,使得爬虫可以进行分布式。可以充分的利用资源(多个ip、更多带宽、同步爬取)来提高爬虫的爬行效率。

分布式爬虫的优点:

  1. 可以充分利用多台机器的带宽。
  2. 可以充分利用多台机器的ip地址。
  3. 多台机器做,爬取效率更高。

分布式爬虫必须要解决的问题:

  1. 分布式爬虫是好几台机器在同时运行,如何保证不同的机器爬取页面的时候不会出现重复爬取的问题。
  2. 同样,分布式爬虫在不同的机器上运行,在把数据爬完后如何保证保存在同一个地方。

安装:

通过pip install scrapy-redis即可安装。

Scrapy-Redis架构:

Scrapy架构图:

Scrapy-Redis架构图:

分布式爬虫架构图:

以上两个图片对比我们可以发现。Item Pipeline在接收到数据后发送给了RedisScheduler调度器调度数据也是从Redis中来的、并且其实数据去重也是在Redis中做的。

编写Scrapy-Redis分布式爬虫:

要将一个Scrapy项目变成一个Scrapy-redis项目只需修改以下三点就可以了:

  1. 将爬虫的类从scrapy.Spider变成scrapy_redis.spiders.RedisSpider;或者是从scrapy.CrawlSpider变成scrapy_redis.spiders.RedisCrawlSpider
  2. 将爬虫中的start_urls删掉。增加一个redis_key="xxx"。这个redis_key是为了以后在redis中控制爬虫启动的。爬虫的第一个url,就是在redis中通过这个发送出去的。
  3. 在配置文件中增加如下配置:
    # Scrapy-Redis相关配置
    # 确保request存储到redis中
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"

    # 确保所有爬虫共享相同的去重指纹
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

    # 设置redis为item pipeline
    ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline': 300
    }

    # 在redis中保持scrapy-redis用到的队列,不会清理redis中的队列,从而可以实现暂停和恢复的功能。
    SCHEDULER_PERSIST = True

    # 设置连接redis信息
    REDIS_HOST = '127.0.0.1'
    REDIS_PORT = 6379
  1. 运行爬虫:
    1. 在爬虫服务器上。进入爬虫文件所在的路径,然后输入命令:scrapy runspider [爬虫名字]
    2. Redis服务器上,推入一个开始的url链接:redis-cli> lpush [redis_key] start_url开始爬取。

搜房网分布式爬虫项目

多台电脑的环境配置

1、获取当前项目所用到的包,pypiwin32==200属于win下的,linux没有,安装时记得删除。

pip3 freeze > requirements.txt

2、如果要在同一台机器上使用多个python版本,可以创建虚拟环境。

pwp@ubuntu:pip3 install virtualenvwrapper

pwp@ubuntu:fang_spider$ which python3
/usr/bin/python3

pwp@ubuntu:fang_spider$ mkvirtualenv -p /usr/bin/python3 crawler-env #创建名为crawler-env的虚拟环境

3、安装

pip3 install -r requirements.txt

4、ubuntu下RedisDesktopManager的安装,redis可视化工具

官方网站:https://redisdesktop.com/download
一句命令行解决:
sudo snap install redis-desktop-manager

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值