[Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(三) —— 数据的持久化——使用MongoDB存储爬取的数据

上一篇:[Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(二) —— 编写一个基本的 Spider 爬取微博用户信息

在上一篇博客中,我们已经新建了一个爬虫应用,并简单实现了爬取一位微博用户的基本信息。这一篇博客就将介绍怎样横向和纵向地扩展爬虫,让爬虫程序循环地爬取用户信息,然后将爬取的用户信息,保存到 MongoDB。

 

扩展爬取范围

1. 完善爬取用户的资料

其实上一篇博客还遗留了部分问题,我们只爬取了用户主页的信息(用户Id、微博数、关注数、粉丝数),还没有爬取用户资料中的信息,包括用户昵称、认证信息、简介、认证、性别、地区等,这一节我们就来实现这部分逻辑。

我们上一篇实现用户基本信息的爬取是在 base_info_parse() 方法中实现的,我们再定义一个 detail_info_parse() 方法来实现用户资料的爬取。我们在用户主页点击“资料”就可以跳转到用户资料页面(https://weibo.cn/1809054937/info),因此我们可以在 base_info_parse() 方法中获取用户资料的 url,当然,仔细观察不难看出所有用户的资料页面 url 都是形如 https://weibo.cn/{user_id}/info 的,因此我们也可以用解析的 user_id 直接组装出 url,这里采用自己组装 url 的方法,然后构造一个新的请求。在 base_info_parse() 方法末尾构建新的爬虫 Request,另外,由于我们得到一位用户的完整信息,是需要将用户基本信息和详细信息组装到一起的,所以我们希望将 base_info_parse() 提取的信息也传递到 detail_info_parse() 方法中去,我们可以采用 meta 这个参数,将提取的信息传递下去,代码如下:

yield scrapy.Request(url='https://weibo.cn/%s/info' % user_id, callback=self.detail_info_parse,
                             headers=self.headers, cookies=self.cookies, meta={'item': load.load_item()})

detail_info_parse() 的完整代码如下:

def detail_info_parse(self, response):
        """
        用户资料解析函数\n
        :param response:
        :return:
        """
        # 获取上一个函数的解析结果
        item = response.meta['item']
        user_id = item.get('user_id')
        # 利用上一个函数的解析结果构造加载器(Loader)
        load = ItemLoader(item=item, response=response)
        selector = scrapy.Selector(response)
        # 如果 user_id 为空,在用户资料页面,再次提取 user_id
        if not user_id:
            ids = selector.xpath('//a[contains(@href,"uid")]/@href').re('uid=(\d{10})')
            ids = list(set(ids))
            user_id = ids[0]
            load.add_value('user_id', user_id)
        nick_name, gender, district, birthday, brief_intro, identify, head_img = '', '', '', '', '', '', ''
        for info in selector.xpath('//div[@class="c"][3]/text()'):
            # 提取个人资料
            nick_name = info.re(u'昵称:(.*)')[0] if info.re(u'昵称:(.*)') else nick_name
            identify = info.re(u'认证:(.*)')[0] if info.re(u'认证:(.*)') else identify
            gender = info.re(u'性别:(.*)')[0] if info.re(u'性别:(.*)') else gender
            district = info.re(u'地区:(.*)')[0] if info.re(u'地区:(.*)') else district
            birthday = info.re(u'生日:(.*)')[0] if info.re(u'生日:(.*)') else birthday
            brief_intro = info.re(u'简介:(.*)')[0] if info.re(u'简介:(.*)') else brief_intro
        # 根据用户填写的地区信息拆分成 省份 和 城市
        province, city = '', ''
        if district:
            extract = district.split(' ')
            province = extract[0] if extract else ''
            city = extract[1] if extract and len(extract) > 1 else ''
        # 合并用户基本信息和详细资料
        load.add_value('province', province)
        load.add_value('city', city)
        load.add_xpath('head_img', '//div[@class="c"]/img[@alt="头像"]/@src')
        load.add_value('username', nick_name)
        load.add_value('identify', identify)
        load.add_value('gender', gender)
        load.add_value('district', district)
        load.add_value('birthday', birthday)
        load.add_value('brief_intro', brief_intro)
        yield load.load_item()

2. 纵向扩展爬取:递归爬取用户的粉丝和关注

目前我们已经基本实现爬取一位微博用户的信息,要实现爬取多用户信息虽然可以在 start_urls 里面构造多个 url 来实现爬取多位用户,但是这样做显然是不现实的,我们注意到微博用户都有自己的粉丝和关注,我们可以通过爬取指定微博用户的关注和粉丝来扩展爬取,因此我们就需要解析用户的关注和粉丝页面来提取数据了。每一个用户的关注页面 url 都是: https://weibo.cn/{user_id}/follow ,粉丝页面 url 都是:https://weibo.cn/{user_id}/fans ,因此我们就可以通过 user_id 来组装出用户的粉丝页面和关注页面:代码如下:

# 用户关注页 url
follows_url = 'https://weibo.cn/%s/follow' % user_id
# 用户粉丝页 url
fans_url = 'https://weibo.cn/%s/fans' % user_id

通过分析粉丝和关注页面,其实两者的页面结构是一样的,因此我们可以用一个方法来分别解析两个页面,代码如下:

def follow_fans_parse(self, response):
        """
        获取关注用户/粉丝用户\n
        :param response:
        :return:
        """
        user_id = response.meta.get('user_id')
        if not user_id:
            user_id = re.compile('https://weibo.cn/(\d{10})/.*').findall(response.url)
            user_id = user_id[0] if user_id else ''
        selector = scrapy.Selector(response)
        # 判断用户数是否超过配置的最大用户数
        type_str = '关注' if str(response.url).find('follow') > 0 else '粉丝'
        self.logger.info('开始构造 [%s] %s爬取请求...' % (user_id, type_str))
        # 解析页面中所有的 URL,并提取 用户 id
        accounts = selector.xpath('//a[starts-with(@href,"https://weibo.cn/u/")]/@href').re(
            u'https://weibo.cn/u/(\d{10})')
        # 去重
        accounts = list(set(accounts))
        # 使用用户 id 构造个人资料、用户主页、关注列表以及粉丝列表的 URL
        urls = []
        [urls.extend(('https://weibo.cn/u/%s' % acc, 'https://weibo.cn/%s/fans' % acc,
                      'https://weibo.cn/%s/follow' % acc)) for acc in accounts]

在上面代码中,我们只是解析了用户关注/粉丝页面的 user_id ,还并没有爬取他们的信息,现在我们来进一步完善程序,使其形成一个闭环,继续爬取用户关注和粉丝的信息以及他们的粉丝和关注的信息。可以看到,我们构造了三种 url,分别是用户主页、关注列表以及粉丝列表的 url,其中关注列表 url 和粉丝列表 url,可以递归调用 follow_fans_parse() 方法,而用户主页可以调用 base_info_parse() 方法,代码如下:

# 使用生成的 URL 构造 request
for url in urls:
   if str(url).find('follow') > 0 or str(url).find('fan') > 0:
       yield scrapy.Request(url=url, callback=self.follow_fans_parse, headers=self.headers,cookies=self.cookies, meta={'user_id': user_id})
   else:
       yield scrapy.Request(url=url, callback=self.base_info_parse, headers=self.headers, cookies=self.cookies)

3. 横向扩展爬取:添加分页爬取

现在我们只是实现了爬取一页的关注/粉丝,在页面中,我们看到对于用户关注和粉丝都是有分页的,每一页只展示 10 位用户,因此我们添加分页的实现,代码如下:

 # 下一页
nextLink = selector.xpath('//div[@class="pa"]/form/div/a/@href').extract()
if nextLink:
   url = 'https://weibo.cn' + nextLink[0]
   self.logger.info('[%s] %s下一页:%s' % (user_id, type_str, url))
   yield scrapy.Request(url=url, callback=self.follow_fans_parse, headers=self.headers, cookies=self.cookies, meta={'user_id': user_id})
else:
   self.logger.info(u'[%s] %s已爬取完毕!' % (user_id, type_str))

最后别忘了在 base_info_parse() 方法中构造 follow_fans_parse() 的请求:

for url in (follows_url, fans_url):
    yield scrapy.Request(url=url, callback=self.follow_fans_parse, headers=self.headers,
                                 cookies=self.cookies, meta={'user_id': user_id})

目前,sina_user.py 的完整代码如下(已隐去 cookies的值):

# -*- coding: utf-8 -*-
import scrapy, time, re
from scrapy.loader import ItemLoader
from sina_scrapy.items import SinaUserItem


class SinaUserSpider(scrapy.Spider):
    # 爬虫的名字,唯一标识
    name = 'sina_user'
    # 允许爬取的域名范围
    allowed_domains = ['weibo.cn']
    # 爬虫的起始页面url
    start_urls = ['https://weibo.cn/u/1809054937']

    def __init__(self):
        self.headers = {
            'Referer': 'https://weibo.cn/u/1809054937',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
        }

        self.cookies = {
            'SCF': 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
            'SUB': 'XXXXXXXXXXXXXXXXXXXXXXXXXX',
            'SUHB': 'XXXXXXXXXXXXXXXXXXXXXXXXX',
            '_T_WM': XXXXXXXXXXXXXXXXXXXXXXXXX
        }

    def start_requests(self):
        """
        构造最初 request 函数\n
        :return:
        """
        for url in self.start_urls:
            yield scrapy.Request(url=url, callback=self.base_info_parse, headers=self.headers, cookies=self.cookies)

    def base_info_parse(self, response):
        """
        微博用户基本信息解析函数\n
        :param response:
        :return:
        """
        # 加载器(Loader)
        load = ItemLoader(item=SinaUserItem(), response=response)
        selector = scrapy.Selector(response)
        # 解析微博用户 id
        re_url = selector.xpath('///a[contains(@href,"uid")]/@href').re('uid=(\d{10})')
        user_id = re_url[0] if re_url else ''
        load.add_value('user_id', user_id)

        follows_url = 'https://weibo.cn/%s/follow' % user_id
        fans_url = 'https://weibo.cn/%s/fans' % user_id
        for url in (follows_url, fans_url):
            yield scrapy.Request(url=url, callback=self.follow_fans_parse, headers=self.headers,
                                 cookies=self.cookies, meta={'user_id': user_id})

        # 微博数
        webo_num_re = selector.xpath('//div[@class="tip2"]').re(u'微博\[(\d+)\]')
        webo_num = int(webo_num_re[0]) if webo_num_re else 0
        load.add_value('webo_num', webo_num)
        # 关注人数
        follow_num_re = selector.xpath('//div[@class="tip2"]').re(u'关注\[(\d+)\]')
        follow_num = int(follow_num_re[0]) if follow_num_re else 0
        load.add_value('follow_num', follow_num)
        # 粉丝人数
        fans_num_re = selector.xpath('//div[@class="tip2"]').re(u'粉丝\[(\d+)\]')
        fans_num = int(fans_num_re[0]) if fans_num_re else 0
        load.add_value('fans_num', fans_num)
        # 记录爬取时间
        load.add_value('crawl_time', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))

        yield scrapy.Request(url='https://weibo.cn/%s/info' % user_id, callback=self.detail_info_parse,
                             headers=self.headers, cookies=self.cookies, meta={'item': load.load_item()})

    def detail_info_parse(self, response):
        """
        用户资料解析函数\n
        :param response:
        :return:
        """
        # 获取上一个函数的解析结果
        item = response.meta['item']
        user_id = item.get('user_id')
        # 利用上一个函数的解析结果构造加载器(Loader)
        load = ItemLoader(item=item, response=response)
        selector = scrapy.Selector(response)
        # 如果 user_id 为空,在用户资料页面,再次提取 user_id
        if not user_id:
            ids = selector.xpath('//a[contains(@href,"uid")]/@href').re('uid=(\d{10})')
            ids = list(set(ids))
            user_id = ids[0]
            load.add_value('user_id', user_id)
        nick_name, gender, district, birthday, brief_intro, identify, head_img = '', '', '', '', '', '', ''
        for info in selector.xpath('//div[@class="c"][3]/text()'):
            # 提取个人资料
            nick_name = info.re(u'昵称:(.*)')[0] if info.re(u'昵称:(.*)') else nick_name
            identify = info.re(u'认证:(.*)')[0] if info.re(u'认证:(.*)') else identify
            gender = info.re(u'性别:(.*)')[0] if info.re(u'性别:(.*)') else gender
            district = info.re(u'地区:(.*)')[0] if info.re(u'地区:(.*)') else district
            birthday = info.re(u'生日:(.*)')[0] if info.re(u'生日:(.*)') else birthday
            brief_intro = info.re(u'简介:(.*)')[0] if info.re(u'简介:(.*)') else brief_intro
        # 根据用户填写的地区信息拆分成 省份 和 城市
        province, city = '', ''
        if district:
            extract = district.split(' ')
            province = extract[0] if extract else ''
            city = extract[1] if extract and len(extract) > 1 else ''
        # 合并用户基本信息和详细资料
        load.add_value('province', province)
        load.add_value('city', city)
        load.add_xpath('head_img', '//div[@class="c"]/img[@alt="头像"]/@src')
        load.add_value('username', nick_name)
        load.add_value('identify', identify)
        load.add_value('gender', gender)
        load.add_value('district', district)
        load.add_value('birthday', birthday)
        load.add_value('brief_intro', brief_intro)
        yield load.load_item()

    def follow_fans_parse(self, response):
        """
        获取关注用户/粉丝用户\n
        :param response:
        :return:
        """
        user_id = response.meta.get('user_id')
        if not user_id:
            user_id = re.compile('https://weibo.cn/(\d{10})/.*').findall(response.url)
            user_id = user_id[0] if user_id else ''
        selector = scrapy.Selector(response)
        # 判断用户数是否超过配置的最大用户数
        type_str = '关注' if str(response.url).find('follow') > 0 else '粉丝'
        self.logger.info('开始构造 [%s] %s爬取请求...' % (user_id, type_str))
        # 解析页面中所有的 URL,并提取 用户 id
        accounts = selector.xpath('//a[starts-with(@href,"https://weibo.cn/u/")]/@href').re(
            u'https://weibo.cn/u/(\d{10})')
        # 去重
        accounts = list(set(accounts))
        # 使用用户 id 构造个人资料、用户主页、关注列表以及粉丝列表的 URL
        urls = []
        [urls.extend(('https://weibo.cn/u/%s' % acc, 'https://weibo.cn/%s/fans' % acc,
                      'https://weibo.cn/%s/follow' % acc)) for acc in accounts]

        # 使用生成的 URL 构造 request
        for url in urls:
            if str(url).find('follow') > 0 or str(url).find('fan') > 0:
                yield scrapy.Request(url=url, callback=self.follow_fans_parse, headers=self.headers,
                                     cookies=self.cookies, meta={'user_id': user_id})
            else:
                yield scrapy.Request(url=url, callback=self.base_info_parse, headers=self.headers, cookies=self.cookies)

        # 下一页
        nextLink = selector.xpath('//div[@class="pa"]/form/div/a/@href').extract()
        if nextLink:
            url = 'https://weibo.cn' + nextLink[0]
            self.logger.info('[%s] %s下一页:%s' % (user_id, type_str, url))
            yield scrapy.Request(url=url, callback=self.follow_fans_parse, headers=self.headers, cookies=self.cookies,
                                 meta={'user_id': user_id})
        else:
            self.logger.info(u'[%s] %s已爬取完毕!' % (user_id, type_str))

现在,我们的程序已经基本实现了爬取微博用户信息的功能(目前没有限制爬取速度,因此在爬取部分用户后,微博服务器会响应 418,这是微博反爬的一种策略,目前只能通过降低爬取的频率来避免出现 418,这个问题会在后面的博客介绍)

 

实现数据的持久化

还记得在 第一篇博客 [Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(一) —— 新建爬虫项目 中分析 Scrapy 的整体架构时介绍到,Spider 爬取的数据,会交给 Item Pipeline 处理。在上面的代码中,detail_info_parse() 方法的最后一行代码:

yield load.load_item()

通过这行代码,Spider 就生成了一个 Item,并将这个 Item 返回给了 Item Pipeline 处理。我们在 Item Pipeline 里面可以将我们爬取的数据存入到 MongoDB 中去。

首先我们在 settings.py 里面定义我们 MongoDB 的连接信息,代码如下:

# MONGODB 主机名
MONGODB_HOST = "127.0.0.1"
# MONGODB 端口号
MONGODB_PORT = 27017
# 数据库名称
MONGODB_DBNAME = "crawl"
# 存放数据的集合名称
MONGODB_COLLECTION = "sina_userinfo"

然后在 Item Pipeline 中得到这些配置,用来初始化 MongoDB 连接,代码如下:

from scrapy.conf import settings
from pymongo import MongoClient

host = settings.get('MONGODB_HOST')
port = settings.get('MONGODB_PORT')
dbname = settings.get('MONGODB_DBNAME')
collection_name = settings.get('MONGODB_COLLECTION')
db = MongoClient(host=host, port=port).get_database(dbname).get_collection(collection_name)

接下来我们要做的很简单,只需要把得到的 Item 保存到 MongoDB 就可以了,我们定义一个 SaveUserInfoPipeline 类,然后定义一个 process_item() 方法,然后将 item 转化成字典类型,保存入库就行了。代码如下:

class SaveUserInfoPipeline(object):
    """
    保存爬取的数据\n
    """

    def __init__(self):
        print('要保存的 Collenction:%s' % collection_name)

    def process_item(self, item, spider):
        data = dict(item)
        print("最终入库数据:%s" % item)
        # 记录不存在则插入,否则更新数据
        db.update_one({'weibo_id': data.get('weibo_id')}, {"$set": data}, True)
        return item

最后一步,在 settings 启用我们定义的 Item Pipeline,代码如下:

ITEM_PIPELINES = {
    'sina_scrapy.pipelines.SaveUserInfoPipeline': 20,
}

后面的数字 20 是代表优先级(取值范围是 1 ~ 999),目前只有一个 Item Pipeline,所以任意指定一个就行。

使用 scrapy crawl sina_user 指令启动爬虫,现在我们已经实现了将爬取的用户信息保存到 MongoDB,但是查看 MongoDB 的数据可以发现,保存的每一项都是一个列表形式,这并不是我们想要的。针对这个问题,我们可以修改 Items 里面关于数据模型的定义,对于每一项数据都只取第一个元素,代码如下:


import scrapy
from scrapy.loader.processors import TakeFirst


class SinaUserItem(scrapy.Item):
    # 微博用户唯一标识
    user_id = scrapy.Field(output_processor=TakeFirst())
    # 用户昵称
    username = scrapy.Field(output_processor=TakeFirst())
    # 微博数量
    webo_num = scrapy.Field(output_processor=TakeFirst())
    # 关注人数
    follow_num = scrapy.Field(output_processor=TakeFirst())
    # 粉丝人数
    fans_num = scrapy.Field(output_processor=TakeFirst())
    # 性别
    gender = scrapy.Field(output_processor=TakeFirst())
    # 地区
    district = scrapy.Field(output_processor=TakeFirst())
    # 省份
    province = scrapy.Field(output_processor=TakeFirst())
    # 地市
    city = scrapy.Field(output_processor=TakeFirst())
    # 生日
    birthday = scrapy.Field(output_processor=TakeFirst())
    # 简介
    brief_intro = scrapy.Field(output_processor=TakeFirst())
    # 认证
    identify = scrapy.Field(output_processor=TakeFirst())
    # 头像 URL
    head_img = scrapy.Field(output_processor=TakeFirst())
    # 爬取时间
    crawl_time = scrapy.Field(output_processor=TakeFirst())

这样我们就实现了我们预期的效果了。

 

总结

这一篇博客,我们实现了从横向和纵向扩展爬取用户信息并将用户信息保存到 MongoDB。在下一节中,我们将对爬虫的一些反爬技术进行介绍,例如添加 IP代理池、Cookies池以及随机选取 User-Agent 等。让我们的爬虫应用反爬机制更加健全。

 

下一篇:[Python 爬虫] 使用 Scrapy 爬取新浪微博用户信息(四) —— 应对反爬技术(选取 User-Agent、添加 IP代理池以及Cookies池 )

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,这是一个比较复杂的问题,需要分几个步骤来完成。 1. 安装和配置Scrapy 首先,你需要安装Scrapy。你可以在终端中使用以下命令安装: ``` pip install scrapy ``` 安装完成后,你需要在Scrapy项目中配置以下文件:`settings.py`、`items.py`、`pipelines.py`。 其中,`settings.py`文件中需要配置一些参数,如下所示: ``` BOT_NAME = 'jd' SPIDER_MODULES = ['jd.spiders'] NEWSPIDER_MODULE = 'jd.spiders' ROBOTSTXT_OBEY = False ITEM_PIPELINES = { 'jd.pipelines.JdPipeline': 300, } FEED_EXPORT_ENCODING = 'utf-8' ``` `items.py`文件中定义了我们要抓取的数据字段,如下所示: ``` import scrapy class JdItem(scrapy.Item): title = scrapy.Field() price = scrapy.Field() comment = scrapy.Field() shop = scrapy.Field() ``` `pipelines.py`文件中我们可以对抓取到的数据进行处理,然后将其存入数据库中,如下所示: ``` import pymysql class JdPipeline(object): def __init__(self): self.connect = pymysql.connect( host='localhost', port=3306, db='jd', user='root', passwd='123456', charset='utf8', use_unicode=True) self.cursor = self.connect.cursor() def process_item(self, item, spider): self.cursor.execute( """insert into jd_goods(title, price, comment, shop) value (%s, %s, %s, %s)""", (item['title'], item['price'], item['comment'], item['shop'])) self.connect.commit() return item ``` 2. 编写Scrapy爬虫 接下来,你需要编写一个Scrapy爬虫爬取京东商品数据。这里以爬取“手机”关键词的商品数据为例,爬取多页数据。 ``` import scrapy from jd.items import JdItem class JdSpider(scrapy.Spider): name = 'jd' allowed_domains = ['jd.com'] start_urls = ['https://search.jd.com/Search?keyword=手机&enc=utf-8'] def parse(self, response): goods_list = response.xpath('//ul[@class="gl-warp clearfix"]/li') for goods in goods_list: item = JdItem() item['title'] = goods.xpath('div[@class="gl-i-wrap"]/div[@class="p-name"]/a/em/text()').extract_first() item['price'] = goods.xpath('div[@class="gl-i-wrap"]/div[@class="p-price"]/strong/i/text()').extract_first() item['comment'] = goods.xpath('div[@class="gl-i-wrap"]/div[@class="p-commit"]/strong/a/text()').extract_first() item['shop'] = goods.xpath('div[@class="gl-i-wrap"]/div[@class="p-shop"]/span/a/text()').extract_first() yield item # 翻页 next_page = response.xpath('//a[@class="pn-next"]/@href') if next_page: url = response.urljoin(next_page.extract_first()) yield scrapy.Request(url, callback=self.parse) ``` 在命令行中输入以下命令运行Scrapy爬虫: ``` scrapy crawl jd ``` 3. 将数据可视化 最后,你需要使用Pyecharts将爬取到的数据进行可视化。这里以柱状图为例,代码如下所示: ``` import pymysql from pyecharts import options as opts from pyecharts.charts import Bar connect = pymysql.connect( host='localhost', port=3306, db='jd', user='root', passwd='123456', charset='utf8', use_unicode=True) cursor = connect.cursor() cursor.execute("""SELECT shop, COUNT(*) FROM jd_goods GROUP BY shop""") data = cursor.fetchall() bar = ( Bar() .add_xaxis([i[0] for i in data]) .add_yaxis("商品数量", [i[1] for i in data]) .set_global_opts(title_opts=opts.TitleOpts(title="京东手机商品店铺分布")) ) bar.render("jd.html") ``` 最后,你可以在浏览器中打开`jd.html`文件,查看生成的柱状图。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值