Nutch学习笔记

Nutch:学习笔记  


apt-get: 命令是Ubuntu下的命令


yum install报错:Another app is currently holding the yum lock
  ps
  rm -rf /var/run/yum.pid :


安装 svn: apt-get install subversion

  用svn工具:获取nutch源码
安装ant : apt-get install ant

用ant编译 nutch,使用build.xml文件



nutch诞生了hadoop,tika,gora

nutch:通过IVY管理jar包


1 安装jdk1.7
2 安装svn
3 安装ant
4 下载eclipse
5 安装eclipse及ivy,svn插件


lucence,solr ,ganglia

首先我们得修改修改nutch的配置文件。加上一些基本的配置信息。不至于是的nutch报错啥的。
ant构建nutch之后。

出现 runtime文件夹,内有俩子文件夹代表两种方式运行
deploy:hadoop运行方式,存储在hdfs中,配置文件打包的方式

local:本地方式,与hadoop完全无关。

这样的设计思想体现低耦合原则

通过nutch的脚本进行判断。


nutch入门重点:在于分析nutch脚本文件。
怎么和hadoop进行连接的。


nutch crawl <urlDir> -solr <solrURl> [-dir d] [-thread n] [-topN N]

[-topN N]:本次fetch时最多的url数
[-depth i]:抓取深度。

是用urlDir中提供的url地址抓取数据。
然后利用solr 引擎进行索引

[-thread n] 指定抓取时开启的线程数。


apt-get installl svn:Ubuntu的安装工具。

ivy与maven的差别
  通过nutch诞生了hadoop,tika,gora

nutch如何跟hadoop进行关联的呢?

是跟nutch的启动脚本来的


nutch crawl


Usage: Crawl <urlDir> -solr <solrURL> [-dir d] [-threads n] [-depth i] [-topN N]



<urlDir>: 表示url地址文件的文件夹。

  -solr <solrURL> :表示如果使用solr进行索引的话,应该提供solr的服务器url地址
<-dir d>: 表示抓取的数据存放的路径。
[-threads n]:表示启动多少个线程来。
[-depth i]:表示的深度是多少,url的深度,因为url中的内容可以也还有url。
            一级一级的嵌套。我们得现在挖取的深度。
[-topN N]: 表示本次fetch的时候抓取的url总个数是多少。

nohup 方式运行,日志放到nohup文件中。


nutch和hadoop是通过nutch脚本。通过hadoop命令吧Apache-nutch-1.7.job
提交给hadoop的jobTracker。

nutch入门重点在于分析nutch脚本文件。
nutch的提升在于研究并深入了解nutch-default.xml文件中的每一个配置项的含义
(结合源代码)
定制开发需要对build.xml文件进行研读

github来作为版本控制工具,git与
github 


错误:

fetcher.Fetcher - Fetcher: No agents listed in 'http.agent.name' property.

需要设置对应的User-Agent头,同时需要删除对应的目录。


配置文件修改后需要借助ant重新进行编译。才能生效。



nutch   readdb 命令:

nutch readdb data/crawldb -stats   统计 data/crawldb 中的信息

svn co   对应的url地址这是用svn工具直接从对应的源码库签出代码。

yum install subversion :安装
yum install ant:安装 ant


runtime
  deploy:跟hadoop相关的。跟hadoop关联是通过nutch的启动脚本进行关联的。
  local :本地模式,完全与hadoop无关的目录。
   
修改配置文件过后需要进行重新编译才能生效。



nutch-default.xml 配置文件。
description,源码

研读build.xml 是定制化开发nutch的必备。

报错之后用百度就行了。



cat n*.out |grep elapsed 


bitbucket: 私有的github


nohup ./bin/nutch crawl urls -dir data -depth 3 -threads 20 &

上面这条命令表示: 在当前目录下的(runtime/local下)
nohup         nohup方式运行
urls         抓取的源地址放在 urls 文件夹下
-dir data     取到的数据放到当前目录的 data目录下。
-depth 3     抓取深度为 3
-threads 20   启动的线程数为20 个

  ./bin/nutch readdb data/crawdb   -stats 

上面这条命令表示在当前目录下(runtime/local下)
readdb : 读取命令
data/crawldb : 统计的源数据存放目录为当前目录的 data/crawldb下
-stats :表示是统计抓取的数据量和操作信息

aptplat.org


nutch-default.xml文件。


linkdb下的 data index 文件
    data:存放url地址
    index: 对url地址建立的索引


segments下的目录
  content
  crawl_fetch
  crawl_generate
  crawl_parse
  crawl_data
  crawl_text




nutch 执行流程:

执行一次 crawl 步骤 depth等于几就执行几次crawl
  a:产生抓取队列,根据当前的实例树线程数进行产生
  b:从网页中开始抓取数据
  c:对抓取的数据进行解析
  d:如果解析到的数据还是一个url就继续 a b c 直到执行的次数达到depth的上限。
解析到数据,放入到linkdb中
同时对数据进行索引分词。
   

看看源代码可好。 fetch文件是比较长的时间


第三讲

data目录文件说明

1 crawlDb
      --current
        --part-0000
              data:存储抓取的数据
      index:data的索引






    bin/nutch   |grep read   搜索 nutch目录下 文件名称为 read的
    有三个read命令对应于data目录下的三个一级子目录
      crawldb:readdb读取该子目录的文件
              查看抓取到的url:

crawldb -dump /usr/local/urls 
                          把抓取到的数据放到 urls目录中,还有根据url去查找当前url的抓取状态等等。总之
              命令多看看,多用用,多试试就行了。
              vi 编辑器中用 /可以搜索内容并定位。
             
      linkdb:readlinkdb读取该子目录的数据
      segments: readseg读取该子目录的数据
                每一次的Generator都会产生一个以当前系统时间为名称的文件夹,下面又有六个
                子文件夹。
                在里面存放一些抓取到的数据。每个目录都是全的。
                content
                crawl_fetch
crawl_generate
crawl_parse
crawl_data
crawl_text 
                每次抓取玩后,都会去更新crawlDB,这是因为抓取到了url后要更新当前抓取的
                  url状态,对于未过期的已经抓取过的url不再抓取。 
               
            nutch中执行某个命令报找不到主类的错误。说明我们每个命令都对应脚本中的某个分支
            同时进一步的映射到对应的Java类,通过一系列的调用机制调度到对应的nutch程序。
             
bin/nutch readseg -dump data/segments/20150103082351 data/segments/20150103082351_dump -noparsetext

通过readseg命令读取 segments中每个子目录中的内容
bin/nutch readseg:   readseg命令

ls -R
:递归列出文件

bin/nutch readseg -get data/segments/2015010308235 http://rongqiang1992.blog.163.com/

获取某个segment中 指定url的信息

   
   
Error: Could not find or load main class data.crawldb.(由于之前执行过crawl命令导致,再次执行inject将会报错。)
    使用 readdb 根据url找对应的url的抓取状态信息时, url最后需要加 / 否则查不出来。



bin/nutch inject data/crawldb urls/   inject 命令产生 data/crawldb



使用inject命令手动注入 url到 crawldb中

bin/nutch generate data/crawldb/ data/segments -topN 20
使用generate命令产生抓取队列。generate 命令产生crawl_generate文件夹


bin/nutch fetch 查看命令的帮助信息。
fetch命令产生content目录和crawl_fetch目录


bin/nutch parse 命令:
parse命令产生crawl_parse parse_data parse_text


  bin/nutch updatedb data/crawldb/ data/segments/20150105044005/
  得会写url的抓取状态。然后继续下一轮的抓取。

   

  generate--fetch--parse--updatedb

  利用nutch+hadoop时,如果数据量大,可以将hdfs的blocksize设置的大些,那么压缩起来空间节省的比较多,读取的效率比较高。
    不用频繁的去拆分blocksize
    三个merge命令。需要merge一些小的碎片
    mergedb
    mergesegs
    mergelinkdb

  hadoop对于处理大文件有天然的优势,对于小文件不太合适

  invertlinks 反转连接生成linkdb 



  bin/nutch domainstats data/crawldb/current host host | domain domain  

连接反转是啥意思。

--计算url的分值用的。我去,原理是这么个问题 
执行完 bin/nutch webgraph -segmentDir   data/segments -webgraphdb data/webgraphdb
执行完成后使用nodedumper命令统计是,所有的url默认的score都为0???




tld:top level domain 顶级域名

webgraphdb中有三个子目录
inlinks:存储所有url对应的输入链接
nodes:每个url对应的输入链接数,输出链接数,及其分值
outlinks:存储所有url对应(拥有)的输出连接

bin/nutch nodedumper -group domain/host max/sum -inlinks/outlinks/scores -output xx_group_dir -webgraphdb data/webgraphdb

对url进行分组,分组的方式可以选择是 按照domain/host方式,即sql中的group by 的列
同时对某个进行分组函数的计算,比如对 -inlinks/outlinks/scores 取max或者sum操作。 


  注入分值。可以将webgraph 中nodes中的已经获取到的url分值注入到crawldb
  也就是说我们可以对已经抓取到的url并且已经有分值的。用一种新的计算方式来计算分值。
  并将该分值更新到原来的crawldb中。
  webgraph使用的是linkrank的分值计算方式
  而scoreupdater用的是scoring-opic的方式进行分值的计算。


疑问: 为什么还有没抓取到的。重定向的url是啥意思,怎么还分临时的。


diff :比较两个文件的不同。


scoring-opic:计算分值的算法插件

scoreupdate:
webgraph :linkrank方式进行分值的计算


freegen:轻量级抓取:   直接指定一个url路径取抓取数据。
这个一般用在当我们的crawldb文件超级大的时候,而我们仅仅只需要对那么几个url进行抓取的时候。


indexchecker :对当前


下载solr-3.6.2的版本 将nutch中才conf目录中的schema.xml
copy到 sorl/example/solr/conf下进行替换。
同时需要修改solr/conf/solrconfig.xml中所有的
<str name="df">text</str> 都替换成为
<str name="df">content</str> 否则启动solr时会报错。
这是因为nutch中的搜索类型默认为content,根本没有text这个类型

  bin/nutch solrindex http://master:8983/solr review/crawldb/ -linkdb review/linkdb/ -dir review/segments/

  使用solr构建索引。以便后期进行搜索


  LUKE:查看索引的工具

  java -jar start.jar &   后台启动solr服务器,8983端口。
同时可以通过ui界面查看:
  http://localhost:8983/solr 

  配置mmseg分词器。 solr/lib目录下。同时修改solr的配置文件。修改分词器设置。


Luke4.0只能支持solr3.6.2版本。LUKE查看索引

配置自定义分词器。


使用mmseg-1.9.1的版本中的类结合LUKE4.0的版本去查看索引的情况并指定某个索引引擎。



solr+nutch整合的时候需要将nutch中的schema.xml文件copy到solr的conf目录下
solr4的版本就copy 对应的schema-solr4.xml
solr3的版本就copy schema.xml文件。
但是copy完成后文件名称必须要为schema.xml不管是3的版本还是4的版本。
solr中的nutch的schema文件名称都必须为schema.xml


3.6.2版本中schema默认的搜索字段是content 根据schema.xml文件中来。
因此我们得修改solr/conf/solrconfig.xml文件中的配置为content

而在4.10的版本中schema.xml文件指定的搜索字段是txt跟
solr/conf/solrconfig.xml相符合。因此不用修改solrconfig.xml文件。





org.apache.solr.common.SolrException: Unable to use updateLog: _version_ field must exist in schema, using indexed="true" or docValues="true", stored="true" and multiValued="false" (_version_ does not exist)
这个错误的解决方案是

修改 schema.xml配置 在fields中增加_version_字段
<field name="_version_" type="long" indexed="true" stored="true"/>


配置solr4.10的分词算法插件为 mmseg-1.9.1的版本。需要将 mmseg-1.9.1/dist下的jar包
copy到 solr/collections/lib下面。
然后修改solr的schema文件的Tokenindexer为mmseg中的类。
将WhiteSpaceXXXFactory, StandardXXXFactory的标签替换为下面的
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex"/>

下面这两默认分词器需要被替换为mmseg4j的分词器工厂类

<tokenizer class="solr.WhitespaceTokenizerFacto ry"/>
<tokenizer class="solr.StandardTokenizerFactory "/>
就是下面这个
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex"/>
<field name="_version_" type="long" indexed="true" stored="true"/>

SOLR3.6.2 VS 4.2.0 



solr
lucene
nutch
hadoop


hadoop 单机本地模式:都是启动了一个java进程

在命令行中进行export 仅仅只对当前session生效的。

伪分布式模式:

which 查询某个命令的路径。
which java查看java的安卓目录。
把下面这句加入到root的home目录中的.bashrc文件的末尾
export PATH=/usr/local/hadoop/hadoop1/bin:$PATH
声明hadoop的环境变量。然后重新登录就生效了。

然后修改hadoop/conf 下的
core-site.xml文件。加入下面几个配置
    <property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
<description>config hdfs</description>
      </property>
      <property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/tmp</value>
<description>config hadoop temp dir</description>
      </property>
 
以及hdfs-site.xml文件,加入

      <property>
<name>dfs.name.dir</name>
<value>/usr/local/dfs/name</value>
<description>config hdfs namenode data dir</description>
      </property>
      <property>
<name>dfs.data.dir</name>
<value>/usr/local/dfs/data</value>
<description>config hdfs datanode data dir</description>
      </property>

      <property>
<name>dfs.replication</name>
<value>1</value>
<description>config hdfs copy quantity</description>
      </property>

  以及mapred-site.xml
   
    <property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
<description>config jobtracker port</description>
      </property>

    <property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value>4</value>
<description>config tasktracker max map task size</description>
      </property>

        <property>
<name>mapred.tasktracker.reduce.tasks.maximum</name>
<value>4</value>
<description>config tasktracker max reduce task size</description>
        </property>
      <property>
<name>mapred.system.dir</name>
<value>/usr/local/mapred/system</value>
<description>config mapred system dir </description>
        </property>
      <property>
<name>mapred.local.dir</name>
<value>/usr/local/mapred/local</value>
<description>config mapred local dir </description>
        </property>


tasktracker
jobtracker
namenode
datanode

hadoop1查看jobtracker 的ui端口50030
            tasktracker的ui端口为50060
            50070查看namenode以及整个分布式文件系统的状态。

三本书:

Hadoop in Action hadoop实战
Hadoop 权威指南 The definitive guide
Hadoop in Practice


曾经由于磁盘空间不足 导致了如下错误。以后建虚拟机的时候多多注意下磁盘空间大小问题
08/01/25 16:31:40 INFO hdfs.DFSClient: org.apache.hadoop.ipc.RemoteException:java.io.IOException: File <filename> could only be replicated to 0 nodes, instead of 1

  hadoop fs -rmr /user/root/urls/urls/

  hadoop fs -lsr /

    下面的命令中提及的目录都是在hadoop中的文件目录。因为这是在deploy模式下运行 的
    bin/nutch crawl urls/   -dir review -threads 20 -depth 2 -topN 2000
    如果-depth不指定默认为5,这个肯定在源代码中有体现

    hadoop1需要hadoop-env.sh修改 JAVA_HOME目录。

  vi /etc/hostname 修改主机名称。
   

  配置hostname修改/etc/hosts 文件   需要将我们的hostname和ip地址配置在最上面。因为linux解析的时候是有个优先级的。
  先找到的先拿走。(这特么也就是我之前老是出问题的原因吧。)

ssh-copy-id :复制公钥到指定的机器


完全分布式 hadoop集群的搭建
三台,一般我们都会将namenode,jobtracker,SecondaryNameNode分开到不同的节点上。
如果都放到同一个节点上,那么压力就会很大。

设置SecondaryNameNode 需要修改 hadoop/conf/master文件
                                以及hdfs-site.xml的dfs.secondary.http.address

修改Namenode   hdfs-site.xml 设置dfs.http.address为namenode的ip及端口号 


修改jobtracker mapred-site.xml 设置 mapred.job.tracker

start-dfs.sh :只能在namenode上执行,启动hdfs
start-mapred.sh 只能在jobtracker上执行 启动jobtracker 
这么一来的话,ssh的范围就比较广泛了。

键步快如飞,就是这么任性好不好你给我去死好不好。


hdfs 回收站 自动清空回收站时间
  <property>
  <name>fs.trash.interval</name>
<value>10080</value>
  </property>


SecondaryNameNode的作用:
根据配置,每个多长时间或者当edits log的size到了多少量的时候。
fs.checkpoint.period:每隔多长时间同步一次。
fs.checkpoint.size:当前edits log到达多少byte后同步一次。

secondaryNamenode从namenode中copy(发送http get 请求获取)当前的edits logs和fsimage

然后根据edits log中记录的操作,将fsimage生成新的fsimage.ckpt
然后让当前的fsimage.ckpt替换fsimage(发送http post请求修改),作为新的fsimage,
edits log 也是最新的。这样每隔一端时间同步一次就好了。

强制停止SecondaryNamenode

./hadoop-daemon.sh stop secondarynamenode 他会删除一个
in_user.lock文件
然后强制合并namenode镜像 
hadoop secondarynamenode -checkpoint force

./hadoop-daemon.sh start secondarynamenode
启动secondaryNamenode


如果SecondaryNameNode还在的话,就不能强制的运行
合并fsimage的操作,会报错的。有一个in_use.lock的文件
同时看了看start-all.sh文件,里面就是调用的
start-dfs.sh 和start-mapred.sh 脚本文件

只要secondaryName的进程还在,我们就还可以用checkpoint来强制性的执行
合并fsimage的操作。

hadoop如何动态的增加节点和删除节点。内部有心跳机制。

1 指定主机名,以及主机名到地址的映射。
2 增加用户和组并且赋予相应的权限。
3 chmod 777 /tmp

4 在master中slaves中增加目标节点主机名。

5 将master中id_rsa.put 放到目标节点上。用于master无密码登陆slave.比如
  我们用start-mapred.sh启动jobtracker时。
    jobtracker需要登陆到tasktracker分配任务,因此需要登陆slave
      我们用start-dfs.sh 启动namenode时,namenode需要登陆到datanode
      需要管控hdfs的datanode节点

6 然后在新增的机器节点上启动 datanode,tasktracker进程 
    hadoop-daemon.sh start datanode
    slaves文件主要是给jobtracker和namenode来使用的。
    masters文件主要是给namenode用的。跟jobtracker无关

试想下如果每个节点都能无限制的连接到namenode,会发生什么?
结果不可想象,因此我们得限制连接namenode的节点个数。

conf/hdfs-site.xml添加下面的配置限制连接namenode
<property>
<name>dfs.hosts</name>
<value>/usr/locah/hadoop/hadoop1/conf/include</value>
<description>permit connect to namenode</description>
</property>

<property>
<name>dfs.hosts.exclude</name>
<value>/usr/locah/hadoop/hadoop1/conf/exclude</value>
<description>have no rights to   connect to namenode</description>
</property>
然后分别添加节点的hostname进include及exclude文件中进行限制和允许

conf/maprer-site.xml 添加下面的配置现在连接jobtracker
  <property>
<name>dfs.hosts</name>
<value>/usr/locah/hadoop/hadoop1/conf/include</value>
<description>permit connect to namenode</description>
</property>

<property>
<name>dfs.hosts.exclude</name>
<value>/usr/locah/hadoop/hadoop1/conf/exclude</value>
<description>have no rights to   connect to namenode</description>
</property>
 


hadoop mradmin -refreshNodes 这个命令使得include的更改生效。

disallowed:不允许

基准测试
  hadoop jar hadoop-test-1.2.1.jar DFSCIOTest -nrFiles 4 -fileSize 256 -resFile test
读测试,写测试。用webui监控hadoop集群实例的运行


Ganglia性能监控linux服务器

apt-get install gmetad :安装数据的收集端
apt-get install rrdtool:数据的存储端,类似数据库,以及数据的展示。

apt-get install ganglia-webfrontend Apache服务器支持。
apt-get install ganglia-monitor 

 
  修改 /etc/ganglia/gmond.conf 将 setuid设置为no
      同时给cluster取个名字。比如为hadoop-cluster这个根下面的要保持一致

  配置gmetad:
  vi /etc/ganglia/gmetad.conf
   
  添加数据来源
  data_source "hadoop-cluster" 10 master slave1 slave210分钟搜集hadoop-cluster集群中的master,slave1,slave2节点的信息
  gridname "Hadoop"
  注意和上面的clustername要保持一致性

  指定web文件夹:
  ln -s /usr/share/ganglia-webfrontend /var/www/ganglia
   
  指定主机名:
   
  vi /etc/apache2/apache2.conf 
  添加 ServerName master 

 
  重启服务:
  /etc/init.d/gmetad restart
  /etc/init.d/ganglia-monitor restart
  /etc/init.d/apache2 restart
   

netstat -nlp |grep :80


aliyun ip地址
123.56.112.62


nginx -c /path/to/nginx.conf

nginx -s reload   重启nginx服务器

安装完成ganglia 服务端,需要在非服务端的节点安装ganglia的客户端

ganglia集成hadoop。
修改hadoop/conf目录下的 hadoop-metrics2.properties文件

我觉得这个问题应该不大


yum install rrdtool ganglia-gmetad ganglia-gmond ganglia-web httpd php


yum install ganglia-gmetad
yum install   ganglia-gmond
yum install   ganglia-web
yum search ganglia-gmond


  rpm -Uvh   http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

  insert into mysql.user(Host,User,Password) values("123.56.112.62","alitest",password("123456"));

  flush privileges;

  --分配aliyuntest数据库的权限给 alitest;
  grant all privileges on aliyuntest.* to alitest@123.56.112.62 identified by '123456';


  2013 lose connection to MYSQL SERVER AT reading initial commnuitcation packet:这个错误是由于没有设置mysql远程连接权限导致的。
   
updaet user set host='123.56.112.62' where user='alitest'; 我们给alitest


--这个选项是配置默认的mapred输出是否采用压缩的方式
<property>
  <name>mapred.output.compress</name>
  <value>false</value>
  <description>Should the job outputs be compressed?
  </description>
</property>


hadoop集群性能瓶颈主要是磁盘读写性能以及网络带宽。因此最好使用
压缩方式进行输出。

--map输出设置压缩。
<property>
  <name>mapred.output.compress</name>
  <value>false</value>
  <description>Should the job outputs be compressed?
  </description>
</property>


--指定压缩算法。


压缩率,压缩时间两个指标:空间和时间需要权衡。 

压缩类型: 块压缩还是记录压缩


<property>
  <name>io.compression.codecs</name>
  <value>org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.SnappyCodec</value>
  <description>A list of the compression codec classes that can be used 
                for compression/decompression.</description>
</property>

指定压缩解压缩算法。


org.apache.hadoop.io.compress.SnappyCodec 这个编码算法需要收懂进行指定。

nutch以deploy方式运行时,nutch的配置和hadoop是整合的。
我姑且猜测下nutch的优先级别高些,
1 nutch本身配置了压缩注入
2 hadoop本身没有配置
结果:采用压法方式注入url


nutch配置不同的压缩方式注入url

  vi conf/nutch-site.xml

  添加


在hadoop中配置snappy压缩的方式。

1 下载解压snappy
2 编译 ./configurate
3 make
4 make install 

5 配置环境变量 
export LD_LIBRARY_PATH=/usr/local/hadoop/hadoop1/lib/native/Linux-amd64-64


多集群组播的原理。同一网段中的机器适用
在gangglia服务端中加入多个data_source,以集群名称命名,后面加上集群中的服务器节点。
  cluster配置中,同一个集群中的机器节点配置相同,包括cluster名称,已经upd端口号必须相同。
不同的集群通过机器名称和upd端口进行区分

每个集群中的集群配置相同。


单播方式


setuid yes 还是no的区别:


?变量记录了命令执行的状态,0表示命令执行成功

<script type="text/javascript" id="wumiiRelatedItems"> </script>
 
阅读(25) | 评论(0)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值