Scrapy框架知识

Scrapy框架架构:

Scrapy框架介绍:
  • 写一个爬虫,需要做很多的事情。比如:发送网络请求、数据解析、数据存储、反反爬虫机制(更换IP代理、设置请求头等)、异步请求等。这些工作如果每次都要从零开始写,比较浪费时间。因此scrapy把一些基础的东西封装好了,在他上边写爬虫可以变得更加高效(爬取效率和开发效率)。
Scrapy框架模块功能介绍:
  • 1.Scrapy Engine(引擎):scrapy框架的核心部分。负责在Spider和ItemPipeline、Downloader、Scheduler中间通信、传递数据等。
  • 2.Spider(爬虫):发送需要爬取的链接给引擎,最后引擎把其他模块请求回来的数据再发送给爬虫,爬虫去解析想要的数据。这部分代码是开发者自己写的。
  • 3.Scheduler(调度器):负责接收引擎发送过来的请求,并按照一定的方式进行排列和整理,负责调度请求的顺序等。
  • 4.Downloader(下载器):负责接收引擎传过来的下载请求,然后去网络上下载对应的数据再交还给引擎。
  • 5.Item Pipeline(管道):负责将Spider(爬虫)传递过去的数据进行保存。
  • 6.Downloader Middlewares(下载中间件):可以扩展下载器和引擎之间通信功能的中间件。
  • 7.Spider Middlewares(Spider中间件):可以扩展引擎和爬虫之间通信功能的中间件。
Scrapy框架安装:
  • pip install scrapy --安装框架
  • pip install pypiwin32 --windows下Scrapy所依赖的包
创建项目:
  • 进入到你想存放的目录。然后使用以下命令创建:
    scrapy startproject [项目名称]
    
  • 使用命令创建一个爬虫:
     scrapy gensipder [爬虫名称] [爬虫域名]
    
项目目录结构:
  1. items.py: 用来存放爬虫爬取下来数据的模型
  2. middlewares.py: 用来存放各种中间件的文件
  3. pipelines.py: 用来将items的模型存储到本地磁盘中
  4. settings.py: 本爬虫的一些配置信息(比如请求头、多久发送一次请求、ip代理池等)
  5. scrapy.cfg: 项目的配置文件
  6. spiders包: 以后所有的爬虫,都是存放在这个里面
糗事百科Scrapy爬虫笔记:
  1. response是一个scrapy.http.response.html.HtmlResponse对象。可以执行xpathcss语法来提取数据
  2. 提取出来的数据,是一个Seletor或者是一个SelectorList对象。如果想要获取其中的字符串。那么应该执行getall或者get方法
  3. getall方法:获取Selector中的所有文本,返回的是一个列表。
  4. get方法:获取Selector中的第一个文本。返回的是一个str类型。
  5. 如果数据解析回来,要传给pipline处理。那么可以使用yield来返回。
  6. item:建议在items.py中定义好模型。以后就不要使用字典。
  7. pipeline: 这个是专门用来保存数据的。其中有三个方法是会经常用的。
    • open_spider(self,spider):当爬虫被打开时执行
    • process_item(self,spider):当爬虫有数据(item)传过来的时候会被调用。
    • close_spider(self,spider):当爬虫关闭的时候会被调用

要激活pipelilne,应该在settings.py中,设置ITEM_PIPELINES

JsonItemExporter和JsonLinesItemExporter:
  • 保存json数据的时候,可以使用这两个类,让操作变得更简单。
    1. JsonItemExporter:这个是每次把数据添加到内存中,最后统一写入到磁盘中,好处是,存储的数据是一个满足json规则的数据。坏处是如果数据量比较大,那么比较耗内存。示例代码如下:
        from scrapy.exporters import  JsonItemExporter  #json导出器
        class QsbkPipeline(object):
                def __init__(self):
                self.fp = open("duanzi.json","wb")
                self.exporter = JsonItemExporter(self.fp,ensure_ascii=False,encoding='utf-8')
                self.exporter.start_exporting()
            def open_spider(self,spider):
                #爬虫开始函数
                pass
            
              def process_item(self, item, spider):
                self.exporter.export_item(item)
                return item
        
            def close_apider(self,spider):
                #爬虫结束后,关闭文件
                self.exporter.finish_exporting()
                self.fp.close()
      
    2. JsonLinesItemExporter:这个是每次调用export_item的时候就把这个item存储到应怕中。坏处是每一个字典是一行,整个文件不是一个满足json格式的文件。好处是每次处理数据的十周直接存储到了硬盘中,这样不会消耗内存,数据也比较安全。示例代码如下:
       from scrapy.exporters import JsonLinesItemExporter
       class QsbkPipeline(object):
             def __init__(self):
               self.fp = open("duanzi.json","wb")
               self.exporter = JsonLinesItemExporter(self.fp,ensure_ascii=False,encoding='utf-8')
       
           def open_spider(self,spider):
               #爬虫开始函数
               pass
         
           def process_item(self, item, spider):
               self.exporter.export_item(item)
               return item
       
           def close_apider(self,spider):
               #爬虫结束后,关闭文件
               # self.exporter.finish_exporting()
               self.fp.close()
         
      
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_extensions = None,
       restrict_xpaths = (),
       tags = ('a','area'),
       attrs = ('href'),
       cononicalize = True,
       unique = True,
       process_value = None 
      )
    
  • 主要参数讲解:

    1. allow:允许的url。所有满足这个正则表达式的url都会被提取。
    2. deny: 禁止的url。所有满足这个正则表达式的url都不会被提取。
    3. allow_domains:允许的域名。只有在这个里面指定的域名的url才会被提取。
    4. deny_doomains: 禁止的域名。所有在这个里面指定的域名的url都不会被提取。
    5. 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中获取到链接后会传递给这个函数,用来过滤不需要爬取的链接。
Request和Response:
Requset对象:
  • Request对象在我们写爬虫,爬取一页的数据需要重新发送一个请求的时候调用。这个类需要传递一些参数,其中比较常用的参数有:

    • url:这个requset对象发送请求的url
    • callback:在下载器下载完成相应的数据后执行的回调函数
    • method:请求的方法。默认为GET方法,可以设置为其他方法。
    • headers:请求头,对于一些固定的设置,放在settings.py中指定就可以了。对于那些非固定的,可以在发送请求的时候指定。
    • meta:比较常用。用于在不同的请求之间传递数据用的。
    • encoding:编码。默认的为utf-8,使用默认的就可以了。
    • dot_filter:表示不由调度器过滤。在执行多次重复的请求的时候用的比较多。
    • errback:在发生错误的时候执行的函数。
Response对象:
  • Response对象一般是由Scrapy给你自动构建的。因此开发者不需要关心如何创建Response对象,而是如何使用它。Response对象有很多属性,可以用来提取数据的。主要有以下属性:

    • meta:从其他请求传过来的meta属性,可以用来保持多个请求之间的数据连接。
    • encoding:返回当前字符串编码和解码的格式。
    • text:将返回来的数据作为unicode字符串返回。
    • body:将返回数据作为byte字符串返回。
    • xpath:xpath选择器。
模拟登录:
  • 想要发送post请求,那么推荐使用scrapy.FormRequest方法。可以方便的指定表单数据。
  • 如果想在爬虫一开始的时候久发送post请求,那么应该重写start_requests方法。在这个方法中,发送post请求
下载文件和图片:
  • Scrapy为下载item中包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的item pipelines。这些pipeline 有些共同的方法和结构(我们称之为media pipeline)。一般来说你会使用Files Pipeline 或者 Images Pipeline。
为什么要选择使用scrapy内置的下载文件的方法:
  • 避免重新下载最近已经下载过的文件。
  • 可以方便的指定文件存储的路径。
  • 可以将下载的图片转换成通用的格式。比如png或jpg。
  • 可以方便的生成缩略图。
  • 可以方便的检测图片的宽和高,确保他们满足最小限制。
  • 异步下载,效率非常高。
Files Pipeline:
  • 当使用Files Pipeline 下载文件的时候,按照以下步骤来完成。

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

    • 定义好一个Item,然后在这个item中定义两个属性,分别为image_urls以及imagesimage_urls是用来存储需要下载的图片的url链接,需要给一个列表。
    • 当文件下载完成后,会把图片下载的相关信息存储到itemimages属性中。比如下载路径、下载的url和文件的校验码等。
    • 在配置文件settings.py中配置IMAGES_STORE,这个配置是用来设置图片下载下来的路径。
    • 启动pipeline:在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline:1
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,执行其他中间件中的相应方法,直到合适的下载器处理函数被调用。
      • 返回Reponse对象:Scrapy将不会调用任何其他的process_request方法,将直接返回这个response对象。已经激活的中间件的process_response()方法则会在每个response返回时被调用。
      • 返回Request对象:不再使用之前的request对象去下载数据,而是根据现在返回request对象返回数据。
      • 如果这个方法中抛出了异常,则会调用process_exception方法。
process_response(self,request,response,spider):
  • 这个时下载器下载的数据到引擎中间会执行的方法。
    • 1.参数:
      • request:request对象。
      • response:被处理的response对象。
      • spider:spider对象。
    • 2.返回值:
      • 返回Response对象:会将这个新的response对象传给其他中间件,最终传给爬虫。
      • 返回Request对象:下载器链被切断,返回的request会重新被下载器调度下载。
      • 如果抛出一个异常,那么调用request的errback方法,如果没有指定这个方法,那么会抛出一个异常。
随机请求头中间件:
  • 爬虫在频繁访问一个页面的时候,这个请求头如果一直保持一致。那么很容易被服务器发现,从而禁止掉这个请求头的访问。因此我们要在访问这个页面之前随机的更改请求头,这样才可以避免爬虫被抓。随机更改请求头,可以在下载中间件中实现。在请求发送给服务器之前,随机的选择一个请求头。这样就可以避免总使用一个请求头了。示例代码如下:

    • 1.在middlewares.py中的设置
      
       #1.引入random
       import random
      
       #2.设置自定义user-agent中间件
       class UserAgentDownloadMiddleware(object):
       #user-agent随机请求头中间件
       USER_AGENTS=[
           'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.    0; Acoo Browser 1.98.744; .NET CLR 3.5.30729)',
           'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.    0; Acoo Browser 1.98.744; .NET CLR 3.5.30729)',
           'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.    0; Acoo Browser; GTB5; Mozilla/4.0 (compatible; MSIE 6.0;     Windows NT 5.1; SV1) ; InfoPath.1; .NET CLR 3.5.30729; .NET     CLR 3.0.30618)',
           'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.    0; SV1; Acoo Browser; .NET CLR 2.0.50727; .NET CLR 3.0.4506.    2152; .NET CLR 3.5.30729; Avant Browser)',
           'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo     Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET     CLR 3.0.04506)',
           'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo     Browser; GTB5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.    1; SV1) ; Maxthon; InfoPath.1; .NET CLR 3.5.30729; .NET CLR 3.    0.30618)',
           'Mozilla/4.0 (compatible; Mozilla/5.0 (compatible; MSIE 8.0;     Windows NT 6.0; Trident/4.0; Acoo Browser 1.98.744; .NET CLR 3.    5.30729); Windows NT 5.1; Trident/4.0)',
           'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Acoo     Browser; InfoPath.2; .NET CLR 2.0.50727; Alexa Toolbar)',
        ]
         def process_request(self,request,spider):
            # 随机产生一个user-agent
            user_agent = random.choice(self.USER_AGENTS)
            request.headers['User-Agent'] = user_agent
      
    • 2.在setting.py中的设置
         #1.将DOWNLOADER_MIDDLEWARES设置成middlewares中自定义中间件
         DOWNLOADER_MIDDLEWARES = {
               'useragent_demo.middlewares.UserAgentDownloadMiddleware': 543,
         }
      
      
  • user-agent列表:http://www.useragentstring.com/pages/useragentstring.php?typ=Browser

ip代理池中间件

代理:

  • 芝麻代理:http://http.zhimaruanjian.com
  • 太阳代理:http://http.taiyangruanjian.com
  • 快代理: http://www.kuaidaili.com
  • 讯代理: http://www.xdaili.cn
  • 蚂蚁代理: http://www.mayidaili.com
使用ip代理池:
  • 示例代码如下:
    • middlewares.py中设置:
         #1.引入random
          import random
      
          #设置ip中间件
          class IPProxyDownloadMiddleware(object):
          #ip代理池中间件
            #此处ip可通过代理获取
            PROXIES= [
                "115.223.127.186:8010",
                "121.237.148.153:3000",
                "202.115.142.147:9200",
                "117.88.177.76:3000",
                "117.88.177.162:3000",
                "121.237.149.113:3000",
                "117.88.176.2:3000",
                "117.88.176.119:3000",
                "117.88.4.151:3000",
                "117.88.5.227:3000"
             ]
            def process_request(self,request,spider):
                proxy = random.choice(self.PROXIES)
                # 因为获取的时候需要加上协议,若是https协议加上https,若是http,则加上http
                request.meta['proxy'] ='https://'+ proxy
      
    • setting.py中设置:
         #1.将DOWNLOADER_MIDDLEWARES设置成middlewares中自定义ip中间件
        DOWNLOADER_MIDDLEWARES = {
              'useragent_demo.middlewares.IPProxyDownloadMiddleware': 100,
        }
      
  • 使用独享代理:
    • middlewares.py中设置:
         class IPProxyDownloadMiddleware(object):
        #ip代理池中间件 - 使用独享代理
          def process_request(self,request,spider):
              proxy = ['独享代理ip及端口']
              user_password = "用户名:密码"
              request.meta['proxy'] ='https://'+ proxy
              #bytes
              b64_user_password = base64.b64encode(user_password.encode('utf-8'))
              request.headers['Proxy-Authorization'] = 'Basic' + b64_user_password.decode('utf-8')
        
      
    • settings.py中设置与代理池设置一致
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值