ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

爬虫入门_9:增量式爬虫

2022-02-20 10:33:14  阅读:245  来源: 互联网

标签:入门 url redis 爬虫 item scrapy 增量 div name


  • 概念:检测网站数据更新的情况,只会爬取网站最新更新出来的数据
  • 增量式爬取的核心是去重,去重方法如下:
    • 思路:通过redis的set集合实现去重的目的

    • 将爬取过程中产生的URL存储到redis的set数据结构中

      • 根据sadd(key,value) 的返回结果,判断此 URL 是否已爬取过

      • 1 表示没有爬取过,则发起请求; 0 表示已爬取过,则不进行请求

      • 示例:在redis中输入以下内容,可以得到下图

        # 向name(set集)中添加一个'jay'
        sadd name jay
        sadd name lily
        sadd name jay  # 再次添加后,会返回0,表示没有添加,因为name中已经有了
        

      在这里插入图片描述

案例

  • 需求:增量式爬取电影网站中最近更新的数据

  • 分析:

    • 指定一个起始的url

    • 基于CrawlSpider获取其他页码链接

    • 基于Rule将其他页码链接进行请求

    • 从每一个页码对应的页面源码中解析出每一个电影详情页的url

    • 核心:检测电影详情页的url之前有没有请求过

      将爬取过的电影详情页的url存储到Redis的set数据结构,实现去重

    • 对详情页的url发起请求,然后解析出电影的名称和简介

    • 进行持久化存储

  • 代码实现

    • 启动redis服务和打开redis终端

      • 启动redis:双击红框,启动服务

    在这里插入图片描述

    • 打开redis客户端:注意要修改编码格式为’UTF-8‘,不然中文显示出来都是16进制的,具体操作如下:

      • 临时修改:只作用于当前窗口,先进入cmd命令窗口(快捷键win键+R)

      • 直接输入“chcp 65001”,回车键(Enter键)执行,这时候该窗口编码已经是UTF-8编码了。

      • 然后进入redis安装的目录下

      在这里插入图片描述

      • 输入redis-cli --raw,进入redis客户端

      在这里插入图片描述

      • 输入flushall : 清空redis的数据
    • 创建一个工程:scrapy startproject moviePro

    • 进入到工程目录中:cd moviePro

    • 创建一个基于CrawlSpider的爬虫文件:

      scrapy genspider -t crawl movie www.xxx.com

    • 编写爬虫文件movie.py

      import scrapy
      from scrapy.linkextractors import LinkExtractor
      from scrapy.spiders import CrawlSpider, Rule
      from moviePro.items import MovieproItem
      from redis import Redis
      
      
      class MovieSpider(CrawlSpider):
          name = 'movie'
          # allowed_domains = ['www.xxx.com']
          start_urls = ['https://www.4567kp.com/frim/index1.html']
      
          rules = (
              Rule(LinkExtractor(allow=r'/frim/index1-\d+\.html'), callback='parse_item', follow=True),
          )
      
          # 创建redis链接对象
          conn = Redis(host='127.0.0.1', port=6379)
      
          # 用于解析每个页码对应页面中的电影详情页的url
          def parse_item(self, response):
              li_list = response.xpath('/html//div[1]/div/div/div/div[2]/ul/li')
              print(len(li_list))
              for li in li_list:
                  # 获取详情页的url
                  detail_url = 'https://www.4567kp.com' + li.xpath('./div/a/@href').extract_first()
      
                  # 将详情页的url存入redis的set中
                  ex = self.conn.sadd('urls', detail_url)
                  # ex == 1 :字符串插入成功
                  # ex == 0 :插入的字符串重复了,利用redis的set集合去重
                  if ex == 1:
                      print("该url没有被爬取过,可以进行数据爬取")
                      yield scrapy.Request(url=detail_url, callback=self.parse_detail)
                  else:
                      print("数据还没有更新,暂无新数据可爬取!")
      
          # 解析详情页中的电影名称和简介,进行持久化存储
          def parse_detail(self, response):
              item = MovieproItem()
              item['name'] = response.xpath('/html//div[1]/div/div/div/div[2]/h1/text()').extract_first()
              item['desc'] = response.xpath('/html//div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract()
              item['desc'] = ''.join(item['desc'])
              yield item
      
    • 在items.py中创建两个属性

      import scrapy
      
      
      class MovieproItem(scrapy.Item):
          # define the fields for your item here like:
          name = scrapy.Field()
          desc = scrapy.Field()
      
    • 在pipelines.py中编写代码

      class MovieproPipeline:
          conn = None
      
          def open_spider(self, spider):
              self.conn = spider.conn
      
          def process_item(self, item, spider):
              dic = {
                  'name': item['name'],
                  'desc': item['desc']
              }
              # print(dic)
              self.conn.lpush('movieData', dic)
              return item
      
    • 修改配置文件settings.py

      USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
      
      # Obey robots.txt rules
      # True:遵从robots协议
      ROBOTSTXT_OBEY = False
      
      # 显示指定的类型的日志信息
      LOG_LEVEL = 'ERROR'
      
      ITEM_PIPELINES = {
         'moviePro.pipelines.MovieproPipeline': 300,
      }
      
    • 在终端中输入:scrapy crawl movie,即可

      • 第一次爬取数据的时候,结果如下

      在这里插入图片描述

      • 第二次爬取该网站数据时,结果如下

      在这里插入图片描述

    • 在redis中查看存储情况

      • keys * : 查看数据存储结果列表

      • smembers urls : 查看urls存储内容

      在这里插入图片描述

      • llen movieData:查看数据大小

      • lrange movieData 0 4:查看前5条样例数据

        在这里插入图片描述

  • 报错

    1. 在运行脚本时,出现了如下的一个bug

      redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a bytes, string, int or float first.
      
      • 问题点:是 因为python中的redis版本过高导致的,需降低版本
      • 解决方法:
        • 查看python中安装的redis的版本,发现是4.0以上的版本
        • 将版本降低到2.10.6:pip install -U redis==2.10.6
        • 再次运行脚本,发现运行成功

参考链接

windows系统修改cmd窗口utf-8编码格式

Python爬虫学习视频

如果本文对你有帮助,记得“点赞、收藏”哦~

标签:入门,url,redis,爬虫,item,scrapy,增量,div,name
来源: https://blog.csdn.net/Amy9_Miss/article/details/123027742

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有