python爬虫--scrapy框架的学习和使用⭐---第二部分

Posted 胜天半月子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python爬虫--scrapy框架的学习和使用⭐---第二部分相关的知识,希望对你有一定的参考价值。


九、CrawlSpider⭐⭐⭐

是一个类,基于Spider的子类。
子类继承父类所有的功能,并能派生出自己的功能!

  • 用于全栈数据的爬取
  1. 基于Spider:手动请求
  2. 基于CrawlSpider
  • 使用流程
  1. 创建工程(同以前不变)
  2. cd XXX
  3. 创建爬虫文件(CrawlSpider):
  • scrapy genspider -t crawl xxx www.xxx.comscrapy genspider -t crawl sun www.xxx.com
  • 链接提取器:根据指定的规则(allow)进行指定的提取
  • 规则解析器:将链接提取器的链接进行指定规则(callback)的解析操作

实战项目

  • 需求

爬取sun网站网站中的编号、新闻标题、新闻内容、编号

  • 分析

爬取的数据没有在同一张页面中

  • 流程
  1. 可以使用链接提取器提取所有的页码链接
  2. 让链接提取器提取所有的新闻详情页
  • 源码解析
  1. sun.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

from sunPro.items import SunproItem,DetailItem



# 需求:爬取sun网站网站中的编号、新闻标题、新闻内容、编号
class SunSpider(CrawlSpider):
    name = 'sun'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://wzzdg.sun0769.com/political/index/politicsNewest?id=1&page=1']

    # 链接提取器:根据指定规则(allow="正则")进行指定链接的提取
    link = LinkExtractor(allow=r'id=1&page=\\d+')
    link_detail = LinkExtractor(allow=r'index\\?id=\\d+')
    
    
    rules = (
        # 规则解析器:将链接提取器的链接进行指定规则(callback)的解析操作
        # 提取链接的个数和回调的次数是相同的
        Rule(link, callback='parse_item', follow=True),

        Rule(link_detail, callback='parse_detail'),

        # follow=True:可以将链接提取器 继续作用到链接提取器提取到的链接 所对应的页面中
        # follow=True:对全栈链接的提取
    )

    # https://wzzdg.sun0769.com/political/politics/index?id=526663 
    # https://wzzdg.sun0769.com/political/politics/index?id=526662


    # 如下两个方法中不可以实现请求传参,因为就没有使用scrapy.Request()   ⭐行星
    # 无法将两个解析方法解析的数据存储到一个item中,因此存储到两个
    # 解析新闻编号和标题
    def parse_item(self, response):
        # xpaht表达式中不可以出现tbody标签
        li_list = response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
        for li in li_list:
            # 新闻编号、新闻标题获取
            new_num = li.xpath('./span[1]/text()').extract_first()
            new_title = li.xpath('./span[@class="state3"]/a/text()').extract_first()
            # print('new_num:',new_num,'new_num_title:',new_title)
            item = SunproItem()
            item['title'] = new_title
            item['new_num'] = new_num

            yield item
        
    # 解析详情页新闻内容、编号
    def parse_detail(self,response):
        new_id = response.xpath('/html/body/div[3]/div[2]/div[2]/div[1]/span[4]/text()').extract_first()
        new_content = response.xpath('/html/body/div[3]/div[2]/div[2]/div[2]/pre/text()').extract_first()
        # print('new_id:',new_id,'new_content:',new_content)
        item = DetailItem()
        item['new_id'] = new_id
        item['new_content'] = new_content

        yield item
  1. items.py

sun.py文件中的两个方法【parse_item,parse_detail】中不可以实现请求传参,因为就没有使用scrapy.Request() ⭐⭐

  • 无法将两个解析方法解析的数据存储到一个item中,因此存储到两个
class SunproItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()
    new_num = scrapy.Field()

class DetailItem(scrapy.Item):
    # define the fields for your item here like:
    new_id = scrapy.Field()
    new_content = scrapy.Field()  
  1. pipelines.py

将数据写入数据库时,如何保证新闻的一致性
通过new_id与new_num 两个数值是一样的

class SunproPipeline:
    # 一定要区分不同的item
    # 如何判定item类型
    def process_item(self, item, spider):
        if item.__class__.__name__ == 'DetailItem':⭐⭐
            print(item['new_id'],item['new_content'])
        else:
            print(item['new_num'],item['title'])
        return item

  1. 最后修改settings.py文件

问题总结

  1. CrawlSpider爬图片的时候遇到了不完整url⭐⭐
  2. re正则的使用

在线正则表达式测试工具


十、分布式爬虫

  • 概念

我们需要搭建一个分布式的集群,让其对一组资源进行分布联合爬取

  • 作用

提升爬取数据的效率

  • 如何实现分布式?

安装一个scrapy-redis的组件

原生的scrapy是不可以实现分布式爬虫,必须让scrapy结合着scrapy-redis组件一起实习那分布式爬虫

  • 为什么原生的scrapy不可以实现分布式?
  1. 调度器不可以被分布式集群共享
  2. 管道不可以被分布式集群共享
  • scrapy-redis组件作用:

可以给原生的scrapy框架提供可以被共享的管道和调度器

  • 实现流程⭐⭐
  1. 创建一个工程【同以往一样】
  2. 创建一个基于CrawlSpider的爬虫文件
  • scrapy startproject fbsPro
  • cd .\\fbsPro\\
  • scrapy genspider -t crawl fbs www.xxx.com
  1. 修改当前的爬虫文件:
  • 导包:from scrapy_redis.spiders import RedisCrawlSpider
  • 注释:start_urls和allowed_domains
  • 添加新属性:redis_key = 'xxxx'可以被共享的调度器队列的名称
  • 编写数据解析相关的操作
  • 将当前爬虫类的父类改为RedisCrawlSpider
  1. 修改配置文件settings.py
  • 指定使用可以被共享的管道
    ITEM_PIPELINES = {
    ‘scrapy_redis.pipelines.RedisPipeline’: 400,
    }
  • 指定调度器
    SCHEDULER ="scrapy_redis.scheduler.Scheduler"
    SCHEDULER_PERSIST = True
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
  • 指定redis服务器
    REDIS_HOST = 'redis服务中的ip地址'# 不指定则默认本地
    REDIS_PORT = 6379
  • redis相关操作配置
  1. 配置redis的配置文件:
  • Linux或者Mac:redis.conf
  • Windows:redis.windows.conf
  • 打开配置文件修改:
    • 将bind 127.0.0.1进行删除
    • 关闭保护模式 :protected-mode yes改为protected-mode no
  1. 结合着配置文件开启redis服务: redis-server 配置文件
  2. 启动客户端 :redis-cli




  • 执行工程
  • scrapy runspider xxx.py
  • 向调度器的队列中放入起使url
  • 调度器的队列在redis的客户端中
    • lpush xxx www.xxx.com

  • 查看数据

  • 爬取到的数据存储在了redis的ProName:items这个数据结构中

十一、增量式爬虫

三类:

  1. 通用爬虫
  2. 聚焦爬虫
  3. 增量式爬虫
  • 概念

检测网站数据更新的情况,只会爬取网站最新更新出来的数据。

  • 需求

获得该网页的名称和简介

  • 分析
  1. 指定一个起使的url
  2. 基于CrawlSpider获取其他页码链接
  3. 基于Rule将其他页码链接进行请求
  4. 从每一个页码对应的页面源码中解析出每一个电影详情页的url
  • 核心:检测电影详情页的url之前有没有请求过🔺
    • 将爬取过的电影详情页的url存储
      • 存储到redis的set结构中【自动去重】
  1. 对详情页的url发起请求,然后解析出电影的名称和简介
  2. 进行持久化存储

  • 主要代码
  1. movie.py

  • pipelines.py

总结

  1. 链接提取器页面提取

以上是关于python爬虫--scrapy框架的学习和使用⭐---第二部分的主要内容,如果未能解决你的问题,请参考以下文章

Python编程基础之(五)Scrapy爬虫框架

python爬虫--scrapy框架的学习和使用⭐⭐⭐---第一部分

Python | 初识爬虫框架Scrapy

Python开源爬虫框架scrapy的了解与认识

python爬虫--scrapy框架的学习和使用⭐---第二部分

python爬虫之scrapy框架