大數(shù)據(jù)之pig詳解_第1頁
大數(shù)據(jù)之pig詳解_第2頁
大數(shù)據(jù)之pig詳解_第3頁
大數(shù)據(jù)之pig詳解_第4頁
大數(shù)據(jù)之pig詳解_第5頁
已閱讀5頁,還剩26頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

Pig詳解目標了解Pig的作用了解Pig的設計思想了解Pig的運行模式掌握PigLatin的基礎知識掌握Pig腳本的運行方法Pig概述Pig是Hadoop的一個擴展,它簡化了Hadoop的編程,提供了一套高級數(shù)據(jù)處理語言,且保持了Hadoop易于擴展與可靠的特性。Pig有兩個主要的組成部分:高級數(shù)據(jù)處理語言PigLatin;依據(jù)可供抽樣的評價機制編譯與運行PigLatin腳本的編譯器。PigLatin是Pig的腳本語言,主要特性:易于編程、自動優(yōu)化、可擴展性Pig的用途Pig的主要應用場景是傳統(tǒng)的數(shù)據(jù)流處理、原生數(shù)據(jù)研究和迭代處理。另外,Pig還可以用來處理離線用戶數(shù)據(jù),對用戶行為進行預測,比如掃描所有的用戶和網(wǎng)站的交互數(shù)據(jù),將用戶進行分類,對每一類建立一個數(shù)學模型,通過分析該模型,可以預測某類用戶對各種類型的廣告或新聞會作出怎樣的反應,從而有針對性地展示這類用戶感興趣的廣告。Pig采用面向數(shù)據(jù)批處理的模式,因此,如果需要處理大量的數(shù)據(jù),如GB或者TB數(shù)量級的數(shù)據(jù),則Pig是個不錯的選擇,但對于需要寫單條或者少量記錄的任務,Pig并非十分適用。Pig的設計思想Pig的主要設計思想:不管數(shù)據(jù)是否有元數(shù)據(jù),Pig都可以操作;不管數(shù)據(jù)是關系型的、嵌套型的或者是非結構化的,Pig都可以操作;Pig還應該很容易擴展,不僅可以操作文件,還可以操作鍵值型的存儲和數(shù)據(jù)庫等。Pig的設計目標并非是只能用于Hadoop平臺。目前,Pig支持用戶自定義字段類型轉(zhuǎn)換函數(shù)、用戶自定義聚合方法函數(shù)和用戶自定義條件式函數(shù),允許用戶隨時整合加入自己的代碼。Pig還有一個優(yōu)化控制器,可以重新排列腳本中的操作過程以達到更好的性能,如果用戶不希望進行這種優(yōu)化,也可以很容易地將該控制器關閉,就不會改變執(zhí)行過程。Pig的運行模式-1Pig有兩種運行模式:Local模式和MapReduce模式,默認使用MapReduce模式。當Pig在Local模式下運行時,Pig只訪問本地一臺主機;而當Pig在MapReduce模式下運行時,它將訪問一個Hadoop集群和HDFS的安裝位置,此時Pig將自動對這個集群進行分配和回收。Pig的Local模式和MapReduce模式都有三種運行方式,分別為GruntShell方式、腳本文件方式和嵌入式程序方式。Pig的運行模式-2Local模式在Local模式下,Pig在單個JVM中訪問本地文件系統(tǒng),該模式用于測試或處理小規(guī)模數(shù)據(jù)集。1)GruntShell方式在Linux終端中執(zhí)行如下命,開啟Pig的Grunt

Shell窗口。

$pig

–x

localGrunt

Shell窗口與Windows系統(tǒng)中的Dos窗口非常類似,用戶可以在這里逐條輸入命令對數(shù)據(jù)進行操作。Pig的運行模式-32)腳本文件方式該方式以腳本文件來進行Pig命令的批處理運行,這些腳本文件實際上是Pig命令的集合。執(zhí)行如下命令,可在本地模式下運行Pig腳本。

$Pig

-x

local

script.Pig其中,script.Pig是要運行的Pig腳本,這里需要正確指定該Pig腳本的位置,否則系統(tǒng)將無法識別,例如,假設Pig腳本位于/root/PigTmp目錄下,則需要寫出此腳本的完整路徑“/root/PigTmp/script.Pig”。Pig的運行模式-43)嵌入式程序方式與運行普通的Java程序相同,首先需要編寫特定的Java程序,并將其編譯生成對應的.class文件或package包,然后調(diào)用main函數(shù)運行該程序??梢允褂萌缦旅睿瑢ava源文件進行編譯。

$javac

-cp

Pig-*.*.*-core.jar

local.javaPig-*.*.*-core.jar為Java源文件編譯過后的打包文件,位于Pig安裝目錄下,local.java為用戶編寫的Java源文件,兩個文件都需要正確指定其位置。編譯完成后,Java會生成一個文件local.class,可以使用如下命令,調(diào)用此文件。

$

java

-cp

Pig-*.*.*-core.jar:.

localPig的運行模式-52.MapReduce模式在MapReduce

模式下,Pig可以訪問整個Hadoop集群,處理大規(guī)模數(shù)據(jù)集。1)GruntShell方式在Linux終端上執(zhí)行如下命令,就可以進入Grunt

Shell的MapReduce模式。

$Pig

-x

mapreduce2)腳本文件方式執(zhí)行如下命令,可以在MapReduce模式下運行Pig腳本文件。$Pig

-x

mapreduce

script.Pig3)嵌入式程序方式與Local模式相同,在MapReduce模式下運行嵌入式程序同樣需要經(jīng)過編譯和執(zhí)行兩個步驟,可以使用如下命令完成相應操作。

javac

-cp

Pig-xxx-core.jar

mapreduce.java

java

-cp

Pig-xxx-core.jar:.

mapreducePigLatinPigLatin是Pig針對MapReduce算法(框架)開發(fā)的一套Shell腳本,類似用戶熟悉的SQL語句,這套腳本可以對加載完畢的數(shù)據(jù)進行排序、過濾、求和、分組(groupby)、關聯(lián)(joining)等操作。PigLatin是一種數(shù)據(jù)流語言,每一步處理都會產(chǎn)生一個新的數(shù)據(jù)集或者一個新的關系,比如下面這個腳本:input=load’data’該腳本中,“input”是加載數(shù)據(jù)集data之后的結果的關系名稱,這里的關系名稱即指通常所說的別名,但需要注意的是,關系名稱與變量不同,一旦聲明了,這個名稱就是不變的了。Pig中的另一個常見概念是字段名稱,它是一個關系所包含的字段(或者稱為列)的名稱。關系名稱和字段名稱都必須以字母字符開頭,后面可以跟上零個或多個字母、數(shù)字或者下劃線。Pig中的關系名稱和字段名稱是大小寫敏感的,例如“A=load’foo’;”和“a=load’foo’;”是不等價的;但是,Pig中的關鍵字是不分大小寫的,例如LOAD和load就是等價的。PigLatin——讀寫和檢測操作符PigLatin中使用的讀/寫操作符如表:操作符說明LOAD語法:alias=LOAD'file'[USINGfunction][ASschema];作用:從文件中裝載數(shù)據(jù)。如果不使用USING選項,則默認使用PigStorage裝載函數(shù)。數(shù)據(jù)可以使用AS選項給出schemaLIMIT語法:alias=LIMITaliasn;作用:限制元素個數(shù)為n,即當作用于alias時,LIMIT返回前n個元素,如不使用,則不能保證哪些元素會被返回DUMP語法:DUMPa1ias;作用:在屏幕上顯示數(shù)據(jù)STORE語法:STOREaliasINTO'directory'[USINGfunction];作用:將一個關系中的數(shù)據(jù)存儲到一個目錄中,并把關系存儲在以“part-nnnnn”為名的文件中,如果不使用USTNG選項特別指定,則默認使用PigStorage存儲函數(shù)PigLatin入門例子:在Pig安裝目錄下有一個文件tutoria1/data/excite-small.log,其中的數(shù)據(jù)分為3列,中間用制表符分隔,第一列為用戶ID,第二列為Unix時間戳,第三列則為查詢記錄。首先,從該文件的4500條記錄中,選取一段樣本如下。3F8AAC2372F6941C 970916091301 bac3F8AAC2372F6941C 970916091354 bloodalcoholcontent3F8AAC2372F6941C 970916091425 3F8AAC2372F6941C 970916091545 3F8AAC2372F6941C 970916093448 3F8AAC2372F6941C 970916093544 breathalizers3F8AAC2372F6941C 970916093551 breathalizers3F8AAC2372F6941C 970916093642 breathalizers3F8AAC2372F6941C 970916093724 minorsinpossesion3F8AAC2372F6941C 970916093848 minorsinpossesion3F8AAC2372F6941C 970916093904 mip然后,在GruntShell中輸入如下命令,將數(shù)據(jù)裝載到一個稱為log的別名中。grunt>log=LOAD‘tutoria1/data/excite-small.Log’AS(user,time,query);LIMIT命令允許指定有多少元組(行)用于返回結果。本例中,如果要查看別名log的4個元組,則可使用以下命令。grunt>1mt=LIMITlog4;grunt>DUMP1mt;返回結果如下。2A9EABFB35F5B954 970916105432 +mdfoods+proteinsBED75271605EBD0C 970916001949 yahoochatBED75271605EBD0C 970916001954 yahoochatBED75271605EBD0C 970916003523 yahoochat執(zhí)行以下命令,完成統(tǒng)計每個用戶發(fā)起的查詢個數(shù)。grunt>log=LOAD'tutorial/data/excite-small.log'AS(user:chararray,time:long,query:chararray);grunt>grpd=GROUPlogBYuser;grunt>cntd=FOREACHgrpdGENERATEgroup,COUNT(log);grunt>STOREcntdINTO'output';部分統(tǒng)計結果如下。002BB5A52580A8ED 18005BD9CD3AC6BB38 1800A08A54CD03EB95 3011ACA65C2BF70B2 501500FAFE317B7C0 150158F8ACC570947D 3018FBF6BFB213E68 1019E9463F6695963 10PigLatin——數(shù)據(jù)類型和schemaPig有6個簡單的原子類型和3個復雜的類型。原子類型包括數(shù)字標量、字符串和二進制對象,類型間轉(zhuǎn)換的實現(xiàn)和常規(guī)方式相同,除非特別聲明,字段默認為bytearray。數(shù)據(jù)類型說明int整數(shù),存儲一個4個字節(jié)大小的帶符號整數(shù),如36long長整型,存儲一個8個字節(jié)大小的帶符號整數(shù),以一個結尾為L的整數(shù)來表示,如50000000000Lfloat浮點數(shù),用4個字節(jié)存儲值,通過一個浮點數(shù)加上f來表示,例如3.14fdouble雙精度浮點數(shù),用8個字節(jié)存儲值,可以使用簡單的格式表示,例如3.25628?hararray字符串或者字符數(shù)組,以加單引號的一系列字符來表示,如’food’,也可以通過轉(zhuǎn)義符反斜杠表示一些特定的字符,例如\n表示回車bytearray一組字節(jié),通過封裝Java的byte[]的DataByteArray類來實現(xiàn),沒有辦法單獨定義一個bytearray常量3個復雜數(shù)據(jù)類型是元組(tuple)、包(bag)和映射表(map)。數(shù)據(jù)類型說明例子tuple(元組)一個定長的包含有序Pig數(shù)據(jù)元素的集合,一個元組相當于SQL中的一行,而元組的字段相當于SQL中的列,其表現(xiàn)形式為逗號分隔的字段,前后用小括號包裹(helloworld,12.5,-2,123)bag(包)元組的無序集合(允許元組重復),表示為逗號分隔的元組,前后由大括號包裹,一個包中的元組不必有相同的schema,甚至字段也不必相同{(helloworld,12.5,-2,123),(2.87,byeworld,10)}map(映射)一組鍵值對,鍵必須是唯一的字符串(chararray),值可以是任意類型的數(shù)據(jù)[‘name’#‘bob’,‘a(chǎn)ge’#21]除了為字段聲明類型,schema還可以為字段命名,使它們更易于引用,用戶可以在LOAD、STREAM和FOREACH命令中使用AS關鍵字為關系定義字段名。在定義schema時,如果遺漏了類型,Pig會默認將bytearray作為最常用的類型。也可以不設置字段的名稱,此時該字段的狀態(tài)為未命名,只能通過位置來引用它。PigLatin——表達式和函數(shù)將表達式和函數(shù)應用于數(shù)據(jù)字段,可以計算出各種數(shù)值。最簡單的表達式為常數(shù)值。表達式也可以引用一個字段的值,既可以通過名字直接引用命名字段的值,也可以使用$n命令引用一個未命名的字段,這里的n是該字段在元組中的位置,從0開始計數(shù)。例如,關系log有3個命名的字段,分別為user、time和query,則可以通過“time”或者“$1”來引用time字段。Pig還支持標準算術表達式、比較表達式、條件表達式、類型轉(zhuǎn)換表達式和布爾表達式,它們常見于大多數(shù)流行的編程語言中,如表表達式說明12,19.2,'helloworld'常數(shù)值,沒有小數(shù)點的數(shù)值為int型,數(shù)字之后帶有l(wèi)或L則為long型;帶有小數(shù)點的數(shù)值為double型,數(shù)字之后有f或者F則為float型+,-,*,/加減乘除+x,-x負號(-),改變一個數(shù)字的符號t(x)將x的值轉(zhuǎn)換為t類型x%yx被y除的余數(shù)(x?y:z)如果x為真則返回y,否則為z,該表達式必須用圓括號包裹==,!=,<,>,<=,>=分別為等于,不等于,小于,大于,不大于,不小于xmatchesregex與字符串x匹配的正則表達式xisnullxisnotnull檢查x是否為空xandy,xorynotx布爾值:與、或、非Pig也支持函數(shù),Pig的內(nèi)置函數(shù)及用法如下:avg用法——avg(expression):計算單列值的平均數(shù),忽略NULL值,在使用groupall或group單列后可使用。contact用法-——contact(expression1,expression2):將兩個字段的值拼接為一個字符串,如果其中一個為NULL,則結果用NULL表示。count用法——count(expression):統(tǒng)計在一個bag中所有元素的數(shù)量,不包含NULL值統(tǒng)計,同時需要以group的支持為前提。diff用法——diff(expression1,expression2),比較一個元組中的兩個fields集合的差異性,與Linux或Python里面的diff函數(shù)類似。IsEmpty用法——IsEmpty(expression):判斷一個bag或map是否為空(沒有數(shù)據(jù)),可以用在filter數(shù)據(jù)過濾中。max用法——max(expression):計算單列中最大的數(shù)值,或者字符串的最大值(字典排序),同count一樣需要group支持。min用法——min(expression):計算單列中最小的數(shù)值,或者字符串的最小值(字典排序),同count一樣需要group支持。size用法——size(expression):計算任何Pig字符串的大小長度,或者集合類型的的長度。subtract用法——subtract(expression1,expression2):對兩個bag里面的元組做差值操作。sum用法——sum(expression):對某列求和,需要提前使用group分組。tokenize用法——tokenize(expression,‘field_delimiter’):按照指定分隔符拆分一句話,然后轉(zhuǎn)成一系列的words。PigLatin——關系型運算符有兩個文件A與B,A文件內(nèi)容如下。0,1,21,3,4B文件內(nèi)容如下。0,5,21,7,8定義關系a與b,代碼如下。grunt>a=load'A'usingPigStorage(',')as(a1:int,a2:int,a3:int);grunt>b=load'B'usingPigStorage(',')as(b1:int,b2:int,b3:int);grunt>DUMPa;(0,1,2)(1,3,4)grunt>DUMPb;(0,5,2)(1,7,8)UNION和SPLITUNION將多個關系歸并在一起,SPLIT則將一個關系分割為多個,代碼如下。grunt>c=UNIONa,b;grunt>DUMPc;(0,1,2)(1,3,4)(0,5,2)(1,7,8)grunt>SPLITcINTOdIF$0==0,eIF$0==1;grunt>DUMPd;(0,1,2)(0,5,2)grunt>DUMPe;(1,3,4)(1,7,8)UNION運算符允許重復,可以使用DISTINCT運算符對關系進行去重(dis=distinctc;)。在c上的SPLIT操作將一個元組傳給另一個關系,如果第一個字段($0)為0,則送到d,如果為1,則送到e。2.FILTER單獨的FILTER運算符會將一個關系裁剪為能夠通過某種測試的元組。grunt>f=FILTERcBY$1>3;grunt>DUMPf;(0,5,2)(1,7,8)上述代碼的意思是:如果第二個字段($1)>3,則將此元組傳送給f。3.SAMPLELIMIT被用于從一個關系中取出指定個數(shù)的元組,而SAMPLE運算符則根據(jù)特定的比例從一個關系中隨機地取樣出元組,用法為“SAMPLE別名size,size范圍[0,1]”,示例如下。grunt>c_sample=SAMPLEc0.4;grunt>DUMPc_sample;(1,3,4)(0,5,2)4.GROUP下列代碼生成了一個新的關系g,它是對c中第3列($2,也被命名為“a3”)的相同元組進行組合的結果。grunt>g=GROUPcBY$2;grunt>DUMPg;(2,{(0,1,2),(0,5,2)})(4,{(1,3,4)})(8,{(1,7,8)})grunt>DESCRIBEc;c:{a1:int,a2:int,a3:int}grunt>DESCRIBEg;g:{group:int,c:{(a1:int,a2:int,a3:int)}}GROUP的輸出通常有兩個字段:第一個字段為組鍵,本例中為a3;第二個字段是一個包(bag),包含組鍵相同的所有元組。觀察變量g的dump值,可以看到它有3個元組,分別對應于變量c中第3列的3個專有值:第一個元組中的包代表c中第3列等于2的所有元組;在第二個元組中的包代表c中第3類等于4的所有元組,以此類推。5.JOIN類似于SQLJOIN,通過兩個或多個表中的鍵將不同的關系聯(lián)系起來,示例如下。grunt>j=JOINaBY$2,bBY$2;grunt>dumpj;(0,1,2,0,5,2)grunt>DESCRIBEj;j:{a::a1:int,a::a2:int,a::a3:int,b::b1:int,b::b2:int,b::b3:int}左外連接示例如下。grunt>l=JOINaBY$2LEFTOUTER,bBY$2;grunt>dumpl;(0,1,2,0,5,2)(1,3,4,,,)全外連接示例如下。grunt>f=JOINaBY$2FULL,bBY$2;grunt>dumpf;(0,1,2,0,5,2)(1,3,4,,,)(,,,1,7,8)右外連接示例如下。grunt>l=JOINaBY$2RIGHTOUTER,bBY$2;grunt>dumpl;(0,5,2,0,1,2)(1,7,8,,,)6.FOREACH和FLATTENFOREACH和FLATTEN瀏覽一個關系中的所有元組,并在輸出中生成新的元組。grunt>k=FOREACHcGENERATEa2,a2*a3;grunt>DUMPk;(1,2)(3,12)(5,10)(7,56)FLATTEN函數(shù)可以移除嵌套的層次,將嵌套式數(shù)據(jù)類型平坦化,幾乎就是建包的反向操作。FLATTEN函數(shù)可以改變由FOREACH…GENERATE產(chǎn)生輸出的結構,其平坦化的特性也會根據(jù)應用方式和應用目標的不同而有所不同。例如,語句FOREACH…GENERATE$0,FLATTEN($1)會為每個輸入元組生成一個形式為(a,b,c)的輸出元組,代碼如下。grunt>k=FOREACHgGENERATEgroup,FLATTEN(c);grunt>DUMPk;(2,0,1,2)(2,0,5,2)(4,1,3,4)(8,1,7,8)grunt>DESCRIBEk;k:{group:int,c::a1:int,c::a2:int,c::a3:int}PigLatin——用戶定義函數(shù)PigLatin設計的基本理念是通過用戶定義函數(shù)(UDF,UserDefinedFunction)獲得擴展性,并為編寫UDF提供一組定義良好的API。Pig支持兩種主要類型的UDF(用戶定義函數(shù)):eval和load/store。其中,load/store函數(shù)僅在LOAD和STORE語句中使用,來幫助Pig讀寫特殊的格式;大多數(shù)的UDF為eval函數(shù),即取出一個字段值,然后返回另一個字段值。例:給出一個學生表(學號,姓名,性別,年齡,所在系),其中含有如下幾條記錄。201000101:李勇:Boy:20:計算機軟件與理論201000102:王麗:Giri:19:計算機軟件與理論201000103:劉花:Girl:18:計算機應用技術201000104:李肖:Boy:19:計算機系統(tǒng)結構201000105:吳達:Boy:19:計算機系統(tǒng)結構201000106:李可:Boy:19:計算機系統(tǒng)結構它們所對應的數(shù)據(jù)類型如下所示,各字段與數(shù)據(jù)類型之間通過冒號(半角英文標點)隔開。Student(Sno:chararray,sname:chararray,Ssex:chararray,Sage:int,Sdept:chararray)下面我們將編寫一個UDF,將所有的小寫字母轉(zhuǎn)換成對應的大寫字母,代碼如下。1importjava.io.IOException;2importorg.apache.Pig.EvalFunc;3importorg.apache.Pig.PigWarning;4importorg.apache.Pig.data.Tuple;5publicclassUPPERextendsEvalFunc<String>{6publicStringexec(Tupleinput)throwsIOException{7if(input!=null&&input.size()!=0&&input.get(0)!=null){8Stringstr=null;9try{10str=(String)input.get(0);11returnstr.toUpperCase();12}catch(ClassCastExceptionvar4){13this.warn("unabletocastinput"+input.get(0),PigWarning.UDF_WARNING_1);14returnnull;15}catch(Exceptionvar5){16this.warn("Errorprocessinginput"+input.get(0),PigWarning.UDF_WARNING_1);17returnnull;18}19}else{20returnnull;21}22}23}使用UDF下列代碼為Pig腳本myscript.Pig,它使用之前編寫的UDF(已編譯為myudf.jar)對上面給出的學生表進行了相應的操作。--myscript.PigREGISTERmyudf.jar;A=LOAD‘Student’usingPigStorage(‘:’)as(Sno:chararrayy,Sname:chararray,Ssex:chararray,Sage:int,Sdept:chararray);B=FOREACHAGENERATEmyudf.UPPER(Ssex);DUMPB;執(zhí)行該腳本文件,命令如下。Pig-xmapreducemyscript.Pig使用參數(shù)-xmapreduce可以指定函數(shù)運行的模式,如果只是為了對函數(shù)進行測試,建議在本地模式下運行,因為對于小文件來說,MapReduce模式的準備時間顯得過長,有時甚至讓用戶覺得MapReduce模式下文件的運行效率比本地模式下還要低,但是為了驗證函數(shù)的通用性,本例會使用MapReduce模式。腳本myscript.Pig的第2行提供了myudf.jar文件的位置,該jar文件中包含我們剛剛編寫的UDF。為了找到myudf.jar文件的位置,Pig會首先檢査環(huán)境變量classpath,如果在classpath中找不到jar文件,Pig將假定地址為絕對地址或一個相對于Pig被調(diào)用位置的地址,如果jar文件依舊不能被發(fā)現(xiàn),系統(tǒng)將返回一個錯誤。操作完成之后,可以在終端上看到Pig輸出的正確結果。BOYGIRLBOYBOYBOYPig腳本——注釋PigLatin支持單行和多行兩種形式的注釋:單行注釋以雙斜杠開始,在行尾結束;多行注釋以“/**/”標記包裹,類似Java中的多行注釋。例如,一個帶有注釋的PigLatin腳本代碼如下。/**Myscript.Pig*用Pig編程*/log=LOAD'excite-small.log’AS(user,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論