zoukankan      html  css  js  c++  java
  • scrapy--使用案例

    1.scrapy框架

    1.1 安装scrapy

    1. pip3 install wheel
    2. 下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
    3. 进入下载目录,执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl
    4. pip3 install pywin32
    5. pip3 install scrapy

    1.2 简单使用

    scrapy创建需要在终端执行命令

    • scrapy startproject proName 创建项目
    • cd proNme 进入项目文件夹
    • scrapy genspider spiderName www.xxx.com 创建一个爬虫文件

    1.3 配置文件

    • 不遵从robots协议

      # Obey robots.txt rules
      ROBOTSTXT_OBEY = False
      
    • 进行UA伪装

      USER_AGENT = '浏览器USER_AGENT'
      
    • 进行日志等级设定:

      LOG_LEVEL = 'ERROR'

    1.4 使用方法

    import scrapy
    class FirstSpider(scrapy.Spider):
        # 爬虫文件的名称:爬虫文件的唯一标识(在spiders子目录下是可以创建多个爬虫文件)
        name = 'first'
        # 允许的域名,一般注释掉
        allowed_domains = ['www.baidu.com']
        # 起始的url列表:列表中存放的url会被scrapy自动的进行请求发送
        start_urls = ['https://www.baidu.com/', 'https://www.sogou.com/']
    
        # 用作于数据解析:将start_urls列表中对应的url请求成功后的响应数据进行解析
        def parse(self, response):
            print(response)
    
    • 项目启动命令
      • scrapy crawl pro_name

    1.5 持久化存储

    • 基于终端指令:

      • 特性:只可以将parse方法的返回值存储到本地的磁盘文件中
      • 存储指令: scrapy crawl spiderName -o filePath
      class XiaopapaSpider(scrapy.Spider):
          name = 'qiubai'
          # allowed_domains = ['www.xxx.com']
          start_urls = ['https://www.qiushibaike.com/text/']
      
          # 基于终端指令的持久化存储操作
          def parse(self, response):
              div_list = response.xpath('//*[@id="content-left"]/div')
              all_data = []
              for div in div_list:
                  # scrapy中的xpath返回的列表的列表元素一定是Selector对象,我们最终想要的解析的数据一定是存储在该对象中
                  # extract()将Selector对象中data参数的值取出
                  # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract()  # 取第一个
                  author = div.xpath('./div[1]/a[2]/h2/text()').extract_first() # 也是取第一个
                  # 列表直接调用extract表示的是将extract作用到每一个列表元素中
                  content = div.xpath('./a[1]/div/span//text()').extract()
                  content = ''.join(content)
                  dic = {'author': author,
                      'content': content }
                  all_data.append(dic)
              return all_data
          
      # response.xpath("xpath 路径")  返回的列表的列表元素是Selector对象,数据存在该对象当中
      # extract()将Selector对象中data参数的值取出
      # .extract_first() # 取第一个值
      # 列表直接调用extract表示的是将extract作用到每一个列表元素中,返回的是一个列表
      

    • 基于管道:实现流程

      1.数据解析
      2.在item类中定义相关的属性
      3.将解析的数据存储或者封装到一个item类型的对象(items文件中对应类的对象)
      4.向管道提交item
      5.在管道文件的process_item方法中接收item进行持久化存储
      6.在配置文件中开启管道

      # 管道中需要注意的细节:
          - 配置文件中开启管道对应的配置是一个字典,字典中的键值表示的就是某一个管道
          - 在管道对应的源文件中其实可以定义多个管道类。一个管道类对应的是一种形式的持久化存储
          - 在process_item方法中的return item表示的是将item提交给下一个即将被执行的管道类
          - 爬虫文件通过yield item只可以将item提交给第一个(优先级最高)被执行的管道
      
    • 将同一份数据持久化到不同的平台中

      • 分析:
        • 1.管道文件中的一个管道类负责数据的一种形式的持久化存储
        • 2.爬虫文件向管道提交的item只会提交给优先级最高的那一个管道类
        • 3.在管道类的process_item中的return item表示的是将当前管道接收的item返回/提交给
          下一个即将被执行的管道类
      # 基于管道的持久化存储
      # 爬虫.py文件,
      def parse(self, response):
          div_list = response.xpath('//*[@id="content-left"]/div')
          all_data = []
          for div in div_list:
              #scrapy中的xpath返回的列表的列表元素一定是Selector对象,我们最终想要的解析的
              #数据一定是存储在该对象中
              #extract()将Selector对象中data参数的值取出
              # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract()
              author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
              #列表直接调用extract表示的是将extract作用到每一个列表元素中
              content = div.xpath('./a[1]/div/span//text()').extract()
              content = ''.join(content)
              #将解析的数据存储到item对象
              item = QiubaiproItem()
              item['author'] = author
              item['content'] = content
              #将item提交给管道
              yield item #item一定是提交给了优先级最高的管道类
              
      
      • items.py文件
      # items.py文件
      class QiubaiproItem(scrapy.Item):
          author = scrapy.Field() #Field可以将其理解成是一个万能的数据类型
          content = scrapy.Field()
      
      • pipelines.py文件
        • 存储到不同的数据平台中
      # pipelines.py文件
      #存储到文件中
      class QiubaiproPipeline(object):
          fp = None
          def open_spider(self,spider): # 重写父类方法,只会执行一次,打开文件
              print('开始爬虫!')
              self.fp = open('qiushibaike.txt','w',encoding='utf-8')
      
          #使用来接收爬虫文件提交过来的item,然后将其进行任意形式的持久化存储
          #参数item:就是接收到的item对象
          #该方法每接收一个item就会调用一次
          def process_item(self, item, spider):
              author = item['author']
              content= item['content']
      
              self.fp.write(author+':'+content+'
      ')
              return item #item是返回给了下一个即将被执行的管道类
      
          def close_spider(self,spider): # 重写父类方法,只会执行一次,关闭文件
              print('结束爬虫!')
              self.fp.close()
      
      #负责将数据存储到mysql
      class MysqlPL(object):
          conn = None
          cursor = None
          def open_spider(self,spider):
              self.conn = pymysql.Connect(host='127.0.0.1',
                                          port=3306,
                                          user='root',
                                          password='123',
                                          db='spider',
                                          charset='utf8')
              print(self.conn)
          def process_item(self,item,spider):
              author = item['author']
              content = item['content']
              sql = 'insert into qiubai values ("%s","%s")'%(author,content)
              self.cursor = self.conn.cursor()
              try:
                  self.cursor.execute(sql)
                  self.conn.commit()
              except Exception as e:
                  print(e)
                  self.conn.rollback()
              return item
          def close_spider(self,spider):
              self.cursor.close()
              self.conn.close()
              
      # 存到redis
      class RedisPL(object):
          conn = None
          def open_spider(self,spider):
              self.conn = Redis(host='127.0.0.1',port=6379)
              print(self.conn)
          def process_item(self,item,spider):
              self.conn.lpush('all_data',item)
              #注意:如果将字典写入redis报错:pip install -U redis==2.10.6
      
      • settings文件
        • 注册定义的管道
      ITEM_PIPELINES = {
          'qiubaiPro.pipelines.QiubaiproPipeline': 300,  # 300表示的是优先级,数字越小,优先级就越大
          'qiubaiPro.pipelines.MysqlPL': 301,
          'qiubaiPro.pipelines.RedisPL': 302,
      }
      

    1.6 发送请求

    1.6.1 自动请求发送:

    def start_requests(self):
        for url in self.start_urls:
        	yield scrapy.Request(url,callback=self.parse)
    

    1.6.2 手动发送请求:

    • 在scrapy中如何进行手动请求发送(GET)
      • 使用场景:爬取多个页码对应的页面源码数据
      • yield scrapy.Request(url,callback)
    • 在scrapy中如何进行手动请求发送(POST)
      data = { #post请求的请求参数
      'kw':'aaa'
      }
      yield scrapy.FormRequest(url,formdata=data,callback)
    #将多个页码对应的页面数据进行爬取和解析的操作
    
    url = 'https://www.qiushibaike.com/text/page/%d/'#通用的url模板
    pageNum = 1
    #parse第一次调用表示的是用来解析第一页对应页面中的段子内容和作者
    def parse(self, response):
        div_list = response.xpath('//*[@id="content-left"]/div')
        all_data = []
        for div in div_list:
            author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
            # 列表直接调用extract表示的是将extract作用到每一个列表元素中
            content = div.xpath('./a[1]/div/span//text()').extract()
            content = ''.join(content)
    
            # 将解析的数据存储到item对象
            item = QiubaiproItem()
            item['author'] = author
            item['content'] = content
    
            # 将item提交给管道
            yield item  # item一定是提交给了优先级最高的管道类
            
       if self.pageNum <= 5:
           self.pageNum += 1
           new_url = format(self.url%self.pageNum)
           #手动请求(get)的发送
           yield scrapy.Request(new_url,callback=self.parse)  # 递归调用parse方法
    

    1.7 scrapy五大核心组件的工作流程

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

  • 相关阅读:
    C语言第三次博客作业---单层循环结构
    C语言第二次博客作业---分支结构
    C语言第一次博客作业——输入输出格式
    C语言--第0次作业
    Codeforces Round #341 Div.2 A. Wet Shark and Odd and Even
    Sources
    kuangbin_SegTree E (HDU 1698)
    (MST) HDOJ 1102 Constructing Roads
    kuangbin_SegTree B (HDU 1754)
    kuangbin_SegTree A (HDU 1166)
  • 原文地址:https://www.cnblogs.com/bigox/p/11447904.html
Copyright © 2011-2022 走看看