Scrapy框架的基本使用-爬取豆瓣Top250的电影

Scrapy框架入门

一、Scrapy架构展示

在这里插入图片描述

1.数据处理流程

  1. 引擎询问蜘蛛需要处理那个网站,并让蜘蛛将第一个需要处理的URL交给它
  2. 引擎让调度器将需要处理的URL放在队列中
  3. 引擎从调度那获取接下来进行爬取的页面
  4. 调度器将下一个爬取的URL返回给引擎,引擎将它通过下载中间件发送到下载器
  5. 当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎,如果下载失败了,引擎会通知调度器记录这个URL,待会再重新下载
  6. 蜘蛛收到下载器的响应并返回爬取到的数据条目,此外还要将需要跟进的新的URL发送给引擎
  7. 引擎将抓取到的数据条目送入数据管道,把新的URL发送给调度器放入队列中

上述操作的第2到第8步会一直重复知道调度器中没有需要请求的URL,爬虫就停止工作

2.准备工作

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy

注:如果安装不成功你需要自己找其他的安装教程,当你在终端输入scrapy version能出来对应的版本号就说明你的Scrapy安装成功了

二、实战案例:基于Scrapy实现一个爬取豆瓣电影 Top250 电影标题、评分和金句等信息的爬虫

创建项目

在你的工程文件下打开终端,输入下面这条命令,创建一个Scrapy项目,项目文件可以直接用scrapy命令生成

scrapy startproject DoubanProject

工程目录如下所示

DoubanProject
|____ DoubanProject
|________ spiders
|____________ __init__.py
|________ __init__.py
|________ items.py
|________ middlewares.py
|________ pipelines.py
|________ settings.py
|____ scrapy.cfg

1.创建你自己的 Spider

Spider是自己定义的类,Scrapy用它来从网页里抓取内容,并解析抓取的结果
在终端执行下面两行命令,

cd DoubanProject		# 进入刚才创建的 DoubanProject 文件夹
scrapy genspider douban movie.douban.com	

执行完后spider文件夹中多了一个douban.py文件

import scrapy


class DoubanSpider(scrapy.Spider):
    # 每个项目唯一的名字,用来区分不同的Spider
    name = "douban"
    # 允许爬取的域名:用来限定start_urls列表中哪些 url 可以进行请求发送
    allowed_domains = ["movie.douban.com"]
    # 起始的 url 列表:该列表中存放的 url 会被 scrapy 自动进行请求的发送
    start_urls = ["https://movie.douban.com/top250"]
	
	# 用作于数据解析:response参数表示的就是请求成功后的响应对象
	# 当 Response 没有指定回调函数时,该方法会默认被调用,它负责处理 Response 并从中提取想要的数据和下一步的请求
    def parse(self, response):
        pass

2.创建 Item

Item是保存爬取数据的容器,它的使用方法和字典类似,创建Item需要继承scrapy.Item类,并且定义为scrapy.Field的字段

items.py

import scrapy


class DoubanprojectItem(scrapy.Item):
    # define the fields for your item here like:
    rank = scrapy.Field()  # 电影排名
    movie_name = scrapy.Field()  # 电影名称
    movie_introduction = scrapy.Field()  # 电影简介
    picture = scrapy.Field()  # 电影海报
    movie_rating = scrapy.Field()  # 电影评分
    evaluators = scrapy.Field()  # 观影人数

3.解析 Response

定义好数据结构以后,接下来我们再接着对douban.py中的我们自己的DoubanSpider 类中的 parse方法进行详细介绍,博主在其他文章中介绍过利用Beautiful SoupXpath以及正则表达式来提取网页数据,不过Scrapy提供了自己的数据提取方法即基于lxml构建的Selector(选择器),同样支持Xpath选择器、CSS选择器、正则表达式

parse()方法的参数responsestart_url里面的链接爬取后的结果,所以在parse()方法中,我们可以直接对response变量包含的内容进行解析,比如浏览请求结果的网页源代码或者进一步分析源代码内容或者找出结果中的链接而得到下一个请求,提取的方式可以是CSS选择器Xpath选择器,我们在这里是用Selector中的Xpath来解析数据,大家对其他解析方式感兴趣可以自行了解

douban.py

import scrapy
from scrapy import Selector, Request
from ..items import DoubanprojectItem


class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]
    start_urls = ["https://movie.douban.com/top250"]

    def parse(self, response):
        sel = Selector(response)
        movie_items = sel.xpath('//div[@class="article"]//ol[@class="grid_view"]/li')
        for movie in movie_items:
            item = DoubanprojectItem()
            item['rank'] = movie.xpath('.//div[@class="pic"]/em/text()').extract_first()	# 电影排名
            item['movie_name'] = movie.xpath('.//div[@class="hd"]//span[1]/text()').extract_first()	# 电影名称
            item['movie_introduction'] = '无' if not movie.xpath('.//div[@class="bd"]//span[@class="inq"]/text()') \
                else movie.xpath('.//div[@class="bd"]//span[@class="inq"]/text()').extract_first()	# 电影简介
            item['picture'] = movie.xpath('.//div[@class="pic"]/a/img/@src').extract_first()	# 电影海报链接
            item['movie_rating'] = movie.xpath('.//div[@class="star"]/span[2]/text()').extract_first()	# 电影评分
            item['evaluators'] = movie.xpath('.//div[@class="star"]/span[4]/text()').extract_first()	# 评价人数
            
            yield item

        nextLink = sel.xpath('//span[@class="next"]/link/@href').extract()
        if nextLink:
            next_page_url = nextLink[0]
            yield Request(url=response.urljoin(next_page_url), callback=self.parse)

Spider的用法

  • 定义爬取网站的动作
  • 分析爬取下来的网页
    Spider类来说,整个爬取循环过程如下所示
  1. 以初始的URL初始化Request并设置回调函数,当该Request请求成功并返回时,Response生成并作为参数传给该回调函数
  2. 在回调函数内分析返回的网页内容,一种解析到有效结果返回字典或者Item对象,另一种解析得到下一个连接,利用此连接构造Request并设置新的回调函数,返回Request等待后序调度
基础属性
常用方法
  • start_requests()
  • parse():当Response没有指定回调函数时,该方法会默认被调用负责处理Response并从中取出想要的数据和下一步的请求,返回一个包含 RequestItem 的可迭代对象

后序Request

我们已经能够实现从初始页面中抓取内容,那么下一页的内容该如何抓取,我们需要从当前的页面中找到信息来生成下一个请求,然后在下一个请求的页面里找到信息再构造下一个请求,这样循环往复迭代从而实现整站的爬取
构造请求时需要用到scrapy.Request,传递两个参数—urlcallback

  • url:请求连接
  • callback:回调函数,当指定该回调函数的请求完成之后获取到响应,引擎会将该响应作为参数传递给这个回调函数

我们在items.py文件中定义了ItemItem可以理解为一个字典,在声明的时候需要实例化

4. Item Pipeline的用法

4.1 Item Pipeline的主要功能
  • 清理HTML数据
  • 验证爬取数据,检查爬取字段
  • 查重并丢弃重复内容
  • 将爬取结果保存到数据库
4.2 基于管道持久化存储操作的流程
  • 数据解析
  • item 类中定义相关的字段属性
  • 将解析的数据封装存储到 item 类型的对象
  • item类型的对象提交给管道进行持久化存储的操作
  • 在管道类的process_item中将其接受到的item对象中存储的数据进行持久化存储的操作
  • 在配置文件settings中开启管道
4.3 核心方法介绍
  • 必须要实现的方法:process_item(item, spider)

功能:进行数据处理或者将数据写入到数据库或文件等操作

def process_item(self, item, spider):
    """
    该方法每接收到一个item就会被调用一次
    :param item: 即被处理的 Item 对象
    :param spider: 生成该 Item 的 Spider 对象
    :return Item对象: 此 Item 对象会被低优先级的 Item Pipeline 的 process_item()方法处理
    :or return DropItem异常: 此 Item 被丢弃,不再进行处理 
    """
    return item

注意: 爬虫文件douban.py提交的item只会传给管道文件pipelines.py中第一个被执行的管道类接受,而pipelines.py中可以有多个管道类,故process_item中的return item表示将item传递给下一个即将被执行的管道类

  • open_spider(self, spider)

Spider开启的时候被自动调用的,故可以在这个方法内做一些初始化操作(开启数据库连接等),参数spider即被开启的Spdier对象

  • close_spider(self, spider)

Spider对象被关闭的时候自动调用的,故可以在这个方法内做一些收尾操作(关闭数据库连接等),参数spider即被关闭的Spdier对象

  • from_crawler(cls, crawler)

类方法,用@classmethod标识,是一种依赖注入的方式,通过crawler对象可以拿到Scrapy的所有核心组件,如全局配置的每个信息,然后创建一个Pipeline实例,参数cls就是Class,拿到配置信息之后返回类对象即可,这个方法的定义主要是用来获取settings.py中的配置的

注:setting.py:在配置文件中打开ITEM_PIPELINES 的相关配置,键名是Pipeline的类名称,键值是调用优先级,是一个数字,数字越小对应的Pipeline越先被调用

ITEM_PIPELINES = {
   "DoubanProject.pipelines.DoubanprojectPipeline": 300,	# 300表示的是优先级,数值越小优先级越高
}
4.4 实战案例代码: pipelines.py

case1: 将数据保存到excel文件

import openpyxl
from .items import DoubanprojectItem


class DoubanprojectPipeline:
    def __init__(self):
        self.wb = openpyxl.Workbook()
        self.sheet = self.wb.active
        self.sheet.title = '豆瓣电影Top250'
        self.sheet.append(('电影排名', '电影名称', '电影简介', '电影海报', '电影评分', '观影人数'))

    def open_spider(self, spider):
        print('开始爬虫...')

    def process_item(self, item: DoubanprojectItem, spider):
        """
        :param item:
        :param spider:
        :return:
        """
        self.sheet.append((item['rank'], item['movie_name'], item['movie_introduction'], item['picture'],
                           item['movie_rating'], item['evaluators']))
        return item

    def close_spider(self, spider):
    	print("爬虫结束....")
        self.wb.save('豆瓣电影数据.xlsx')

在你的终端命令行输入scrapy crawl douban 后按下回车,等待scrapy执行完毕,在你的工程目录下会出现一个豆瓣电影数据.xlsx文件,用wps打开即可以看到下面这个效果

部分结果展示
在这里插入图片描述
case2: 将数据保存到MySQL
要将数据保存至MySQL数据库,首先要安装MySQL,关于MySQL的安装大家可以参考网上其他教程,能够出现下面这个图片说明安装成功了
在这里插入图片描述

  1. 在MySQL中创建数据库(确定你的MySql版本)
create database douban_movie;     # mysql8.0默认就是utf8mb4;
create database douban_movie default charset=utf8mb4;    # mysql8.0之前的版本
  1. 博主这里创建的数据库名称为douban_movie,切换到你创建的数据库
use douban_movie;
  1. 在你的数据库下建表
CREATE TABLE movie_data(
    rank varchar(20),
    movie_name varchar(30),
    movie_introduction varchar(100),
    picture varchar(100),
    movie_rating varchar(100),
    evaluators varchar(100)
    )character set=utf8;
  1. pipelines.py文件中的代码
import pymysql
from .items import DoubanprojectItem


# piplines.py中的一个管道类对应将一组数据存储到一个平台或者载体中
class MysqlPipeline:
    def __init__(self, host, database, user, password, port):
        self.host = host
        self.database = database
        self.user = user
        self.password = password
        self.port = port

    @classmethod
    def from_crawler(cls, crawler):
    	""""""
        return cls(
            host=crawler.settings.get('MYSQL_HOST'),
            database=crawler.settings.get('MYSQL_DATABASE'),
            user=crawler.settings.get('MYSQL_USER'),
            password=crawler.settings.get('MYSQL_PASSWORD'),
            port=crawler.settings.get('MYSQL_PORT')
        )

    def open_spider(self, spider):
        print('打开数据库连接....')
        self.db = pymysql.connect(host=self.host, user=self.user, password=self.password, database=self.database,
                                  port=self.port, charset='utf8')

        self.cursor = self.db.cursor()

    def close_spider(self, spider):
        print('关闭数据库连接...')
        self.db.close()

    def process_item(self, item, spider):
        data = dict(item)
        keys = ', '.join(data.keys())
        print(keys)
        values = ', '.join(['%s'] * len(data))
        print(values)
        sql = "insert into movie_data (%s) values (%s)" % (keys, values)
        self.cursor.execute(sql, tuple(data.values()))
        self.db.commit()
        return item		# 传递给下一个即将被执行的管道类

**注:**修改settings.py文件对项目进行配置

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    "DoubanProject.pipelines.MysqlPipeline": 301,
}

# 连接你本地MYSQL的相关配置
MYSQL_HOST = 'localhost'
MYSQL_DATABASE = 'douban_movie'
MYSQL_PORT = 3306
MYSQL_USER = 'root'
MYSQL_PASSWORD = 'your password'

保存到MySQL部分结果展示
在你的终端命令行输入scrapy crawl douban 后按下回车,等待scrapy执行完毕,切换到你的mysql终端,输入slect * form movie_data即可看到下面的数据,当然你也可以用数据库管理工具MySQLWorkbench或者Navicat打开查看
在这里插入图片描述

到此,其实你可以按照博主上面介绍的步骤,复制上面的代码到对应的文件下面,修改settings.py文件中的配置,使用命令行输入开启爬虫就能得到上面的结果,非常的酷炫哈~,不过在某些情况下你可能运行不出来,或者爬取不到数据,第一种情况是豆瓣修改了前端网页,这个时候你修改Xpath页面解析元素定位的方式即可,第二种情况网站的反爬机制限制了你的访问,这个时候你还需要接着往下看!!!

三、Middleware的用法(扩展)有个初步了解即可

1. Downloader Middleware 的用法

Downloader Middleware 即下载中间件,它是处于Scrapy的Request和Response之间的处理模块
Scheduler从队列中拿出一个Request发送给Downloder执行下载,这个过程会经过Downloader Middleware的处理,当DownloaderRequest下载完成得到Response返回给Spider时会再次经过Downloader Middleware处理
Downloader Middleware的功能十分强大,修改User-Agent、处理重定向、设置代理、失败重试、设置Cookie等功能都需要它来实现

案例演示一:修改User-Agent

我们知道UA伪装的目的是让网站将我们爬虫发起的请求伪装成浏览器访问网站的请求,我们可以通过如下方式构造一个虚假的UA,让网站把我们的请求当成是浏览器发过来的请求

middlewares.py

from faker import Faker


class doubanRandomUserAgentMiddlewares:
    def __init__(self):
        self.faker = Faker()  # 看名字就知道是干啥的

    def process_request(self, request, spider):
        request.headers.setdefault('User-Agent', self.faker.user_agent())
案例演示二:设置Cookie

豆瓣网站的反爬机制对访问频率有限制,对于未登录的请求,如果访问过快,网站会返回403 Forbidden状态码,那么你将爬不到任何数据,这个时候你需要登录豆瓣网站,然后按下F12打开开发者工具,将你登录之后的Cookie赋值粘贴到下面的字符串中
在这里插入图片描述
middlewares.py

def get_douban_cookies():
    cookie_str = 'your cookies'
    cookie_dict = {i.split('=')[0]: i.split('=')[1] for i in cookie_str.split('; ')}
    return cookie_dict


COOKIE_DICT = get_douban_cookies()  # 获取cookie,为了不每次调用函数,先将其转换成值



class DoubanDownloaderMiddleware:

    def process_request(self, request, spider):
        request.cookies = COOKIE_DICT  # 将获取到的cookie写入请求
        return None

注:settings.py文件中的配置如下

DOWNLOADER_MIDDLEWARES = {
   "DoubanProject.middlewares.DoubanDownloaderMiddleware": 543,
   "DoubanProject.middlewares.doubanRandomUserAgentMiddlewares": 544,
}
案例三:设置代理【这里可不配,只做演示】

如果频繁的访问,爬取数据,网站会对直接封掉你的访问IP,这个时候需要设置代理IP,关于代理IP的设置和获取就是另一个大篇幅了,这里不做细讲,在这个案例中爬取你稍微注意一下基本不会封掉IP,如果要设置代理IP,你需要有一批可用的IP地址,这个一般需要付费购买,当你有了IP以后,配置如下
middlewares.py

核心方法

  • process_request(request, spider)

RequestScrapy引擎调度给Downloader之前,process_request()方法就会被调用,在Request从队列里被调度出来到Downloader下载执行之前,我们都可以用process_request()方法对Request进行处理

def process_request(self, request, spider):
	"""
	
	"""
    # Called for each request that goes through the downloader
    # middleware.

    # Must either:
    # - return None: continue processing this request
    # - or return a Response object:更低优先级的 Downloader Middleware 就不会被调用
    # - or return a Request object:更低优先级的 Downloader Middleware 的 process_request() 会停止执行
    # - or raise IgnoreRequest: process_exception() methods of
    #   installed downloader middleware will be called
    return None
  • process_response(request, response, spider)

Downloader执行Request下载之后会得到对应的Response,在Scrapy引擎将Response发送给Spider进行解析之前,可以用process_response()方法来对Response进行处理

2. Spider Middleware的用法(在这个案例中不涉及)

简单介绍,大家有兴趣可以深入了解

当Downloader生成Response之后,Response会被发送给Spider,在发送给Spider之前,Response会首先经过

  • Downloader 生成的 Response 发送给 Spider 之前对 Response 进行处理
  • Spider 生成的 Request 发送给 Scheduler 之前对 Request 进行处理
  • Spider 生成的 Item 发送给 Item Pipeline 之前对 Item 进行处理

注:Spider Middleware的使用频率没有 Downloader Middleware高,在必要的情况下可以用来方便数据的处理

四、结语

本文给大家介绍了Scrapy的框架以及Scrapy的基本用法,通过一个爬取豆瓣电影Top250的案例展示了Scrapy的威力,相比于requestsScrapy最大的方便除了在于框架化,流程化,其实最主要的还是在于Scrapy中的请求是异步的,对于海量数据的爬取是requests无法比拟的

上面的根据每个知识点讲解了每部分代码的功能,下面附上可以直接运行的代码,【下面只将爬取数据保存至excel文件中】大家可以先赋值粘贴运行感受一下Scrapy的威力与魅力再去深入了解每个部分的功能也可~
安装对应的三方库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple openpyxl

按照第一节中的步骤创建号工程目录之后
douban.py

import scrapy
from scrapy import Selector, Request
from ..items import DoubanprojectItem


class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]
    start_urls = ["https://movie.douban.com/top250"]

    def parse(self, response):
        sel = Selector(response)
        movie_items = sel.xpath('//div[@class="article"]//ol[@class="grid_view"]/li')
        for movie in movie_items:
            item = DoubanprojectItem()
            item['rank'] = movie.xpath('.//div[@class="pic"]/em/text()').extract_first()	# 电影排名
            item['movie_name'] = movie.xpath('.//div[@class="hd"]//span[1]/text()').extract_first()	# 电影名称
            item['movie_introduction'] = '无' if not movie.xpath('.//div[@class="bd"]//span[@class="inq"]/text()') \
                else movie.xpath('.//div[@class="bd"]//span[@class="inq"]/text()').extract_first()	# 电影简介
            item['picture'] = movie.xpath('.//div[@class="pic"]/a/img/@src').extract_first()	# 电影海报链接
            item['movie_rating'] = movie.xpath('.//div[@class="star"]/span[2]/text()').extract_first()	# 电影评分
            item['evaluators'] = movie.xpath('.//div[@class="star"]/span[4]/text()').extract_first()	# 评价人数
            
            yield item

        nextLink = sel.xpath('//span[@class="next"]/link/@href').extract()
        if nextLink:
            next_page_url = nextLink[0]
            yield Request(url=response.urljoin(next_page_url), callback=self.parse)

items.py

import scrapy


class DoubanprojectItem(scrapy.Item):
    # define the fields for your item here like:
    rank = scrapy.Field()  # 电影排名
    movie_name = scrapy.Field()  # 电影名称
    movie_introduction = scrapy.Field()  # 电影简介
    picture = scrapy.Field()  # 电影海报
    movie_rating = scrapy.Field()  # 电影评分
    evaluators = scrapy.Field()  # 观影人数

pipelines.py

import openpyxl
from .items import DoubanprojectItem


class DoubanprojectPipeline:
    def __init__(self):
        self.wb = openpyxl.Workbook()
        self.sheet = self.wb.active
        self.sheet.title = '豆瓣电影Top250'
        self.sheet.append(('电影排名', '电影名称', '电影简介', '电影海报', '电影评分', '观影人数'))

    def open_spider(self, spider):
        print('开始爬虫...')

    def process_item(self, item: DoubanprojectItem, spider):
        """
        :param item:
        :param spider:
        :return:
        """
        self.sheet.append((item['rank'], item['movie_name'], item['movie_introduction'], item['picture'],
                           item['movie_rating'], item['evaluators']))
        return item

    def close_spider(self, spider):
    	print("爬虫结束....")
        self.wb.save('豆瓣电影数据.xlsx')

settings.py

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
   "DoubanProject.middlewares.DoubanDownloaderMiddleware": 543,
   "DoubanProject.middlewares.doubanRandomUserAgentMiddlewares": 544,
}

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   "DoubanProject.pipelines.DoubanprojectPipeline": 300,
}

# 如果做了第三步在Middlewares中做了对应的伪装UA的配置,这里可以不用加
USER_AGENT = '你浏览器的User-Agent'
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
好的,以下是爬取豆瓣电影的简单示例: 1. 首先,我们需要安装Scrapy。可以在命令行中使用以下命令进行安装: ``` pip install scrapy ``` 2. 创建一个Scrapy项目。在命令行中使用以下命令创建一个项目: ``` scrapy startproject douban_movie ``` 这将创建一个名为`douban_movie`的文件夹,其中包含了Scrapy项目的基本结构。 3. 创建一个Spider。在Scrapy中,Spider是用于定义如何爬取网站的类。我们可以创建一个Spider来爬取豆瓣电影信息。在`douban_movie/spiders`文件夹下创建一个名为`douban_spider.py`的文件,并添加以下代码: ```python import scrapy class DoubanSpider(scrapy.Spider): name = 'douban' allowed_domains = ['movie.douban.com'] start_urls = ['https://movie.douban.com/top250'] def parse(self, response): pass ``` 在上面的代码中,我们定义了一个名为`DoubanSpider`的Spider,并设置了起始URL和允许的域名。在`parse`方法中,我们将会编写解析响应的代码。 4. 编写解析代码。在`parse`方法中,我们需要编写代码来解析响应并提取我们需要的信息。以下是一个简单的例子,用于提取豆瓣电影Top250中每个电影的名称和评分: ```python import scrapy class DoubanSpider(scrapy.Spider): name = 'douban' allowed_domains = ['movie.douban.com'] start_urls = ['https://movie.douban.com/top250'] def parse(self, response): for movie in response.xpath('//div[@class="info"]'): yield { 'title': movie.xpath('a/span[@class="title"]/text()').extract_first(), 'rating': movie.xpath('div[@class="star"]/span[@class="rating_num"]/text()').extract_first(), } ``` 在上面的代码中,我们使用XPath来提取电影名称和评分,并使用`yield`将结果返回给Scrapy框架。 5. 运行Spider。在命令行中使用以下命令来运行Spider: ``` scrapy crawl douban -o movies.csv ``` 在上面的命令中,`douban`是Spider的名称,`movies.csv`是我们将结果保存到的文件名。运行完成后,我们将在当前目录下找到一个名为`movies.csv`的文件,其中包含了豆瓣电影Top250中每个电影的名称和评分。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_lover_forever

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值