Python黑帽編程2.3 字符串、列表、元組、字典和集合


Python黑帽編程2.3  字符串、列表、元組、字典和集合

本節要介紹的是Python里面常用的幾種數據結構。通常情況下,聲明一個變量只保存一個值是遠遠不夠的,我們需要將一組或多組數據進行存儲、查詢、排序等操作,本節介紹的Python內置的數據結構可以滿足大多數情況下的需求。這一部分的知識點比較多,而且較為零散,需要認真學習。

2.3.1  字符串

字符串是 Python 中最常用的數據類型。我們可以使用引號('")來創建字符串。

創建字符串很簡單,只要為變量分配一個值即可。例如:

var1 ='Hello World!'

var2 ="Python Runoob"

Python訪問字符串中的值

Python不支持單字符類型,單字符也在Python也是作為一個字符串使用。

Python訪問子字符串,可以使用方括號來截取字符串,如下實例:

var1 ='Hello World!'

var2 ="Python Runoob"

 

print"var1[0]: ", var1[0]

print"var2[1:5]: ", var2[1:5]

以上實例執行結果:

2

 

Python字符串更新

你可以對已存在的字符串進行修改,並賦值給另一個變量,如下實例:

#!/usr/bin/python

# -*- coding: UTF-8 -*-

 

var1 ='Hello World!'

 

print"更新字符串 :- ", var1[:6]+'Runoob!'

運行結果如下:

3

Python轉義字符

在需要在字符中使用特殊字符時,python用反斜杠(\)轉義字符。如下表:

轉義字符

描述

\(在行尾時)

續行符

\\

反斜杠符號

\'

單引號

\"

雙引號

\a

響鈴

\b

退格(Backspace)

\e

轉義

\000

\n

換行

\v

縱向制表符

\t

橫向制表符

\r

回車

\f

換頁

\oyy

八進制數,yy代表的字符,例如:\o12代表換行

\xyy

十六進制數,yy代表的字符,例如:\x0a代表換行

\other

其它的字符以普通格式輸出

 

Python字符串運算符

下表實例變量a值為字符串"Hello"b變量值為"Python"

操作符

描述

實例

+

字符串連接

a + b 輸出結果: HelloPython

*

重復輸出字符串

a*2 輸出結果:HelloHello

[]

通過索引獲取字符串中字符

a[1] 輸出結果 e

[ : ]

截取字符串中的一部分

a[1:4] 輸出結果ell

in

成員運算符 - 如果字符串中包含給定的字符返回 True

H in a 輸出結果 1

not in

成員運算符 - 如果字符串中不包含給定的字符返回 True

M not in a 輸出結果 1

r/R

原始字符串 - 原始字符串:所有的字符串都是直接按照字面的意思來使用,沒有轉義特殊或不能打印的字符。原始字符串除在字符串的第一個引號前加上字母"r"(可以大小寫)以外,與普通字符串有着幾乎完全相同的語法。

print r'\n' 輸出 \n  print R'\n'輸出 \n

%

格式字符串

請看下一章節

實例如下:

#!/usr/bin/python

# -*- coding: UTF-8 -*-

 

a ="Hello"

b ="Python"

 

print"a + b 輸出結果:", a + b

print"a * 2 輸出結果:", a *2

print"a[1] 輸出結果:", a[1]

print"a[1:4] 輸出結果:", a[1:4]

 

if("H"in a):

    print"H 在變量 a "

else:

    print"H 不在變量 a "

 

if("M"notin a):

    print"M 不在變量 a "

else:

    print"M 在變量 a "

 

print r'\n'

print R'\n'

以上程序執行結果為:

4

Python字符串格式化

Python 支持格式化字符串的輸出。盡管這樣可能會用到非常復雜的表達式,但最基本的用法是將一個值插入到一個有字符串格式符 %s 的字符串中。

Python 中,字符串格式化使用與 C sprintf 函數一樣的語法。

比如下面的代碼:

#!/usr/bin/python

 

print"My name is %s and weight is %d kg!"%('Zara',21)

運行結果為:

5

 

python字符串格式化符號一覽表:

      

描述

      %c

 格式化字符及其ASCII

      %s

 格式化字符串

      %d

 格式化整數

      %u

 格式化無符號整型

      %o

 格式化無符號八進制數

      %x

 格式化無符號十六進制數

      %X

 格式化無符號十六進制數(大寫)

      %f

 格式化浮點數字,可指定小數點后的精度

      %e

 用科學計數法格式化浮點數

      %E

 作用同%e,用科學計數法格式化浮點數

      %g

 %f%e的簡寫

      %G

 %f %E 的簡寫

      %p

 用十六進制數格式化變量的地址

格式化操作符輔助指令:

符號

功能

*

定義寬度或者小數點精度

-

用做左對齊

+

在正數前面顯示加號( + )

<sp>

在正數前面顯示空格

#

在八進制數前面顯示零('0'),在十六進制前面顯示'0x'或者'0X'(取決於用的是'x'還是'X')

0

顯示的數字前面填充'0'而不是默認的空格

%

'%%'輸出一個單一的'%'

(var)

映射變量(字典參數)

m.n.

m 是顯示的最小總寬度,n 是小數點后的位數(如果可用的話)

 

Python三引號(triple quotes

python中三引號可以將復雜的字符串進行復制python三引號允許一個字符串跨多行,字符串中可以包含換行符、制表符以及其他特殊字符。

三引號的語法是一對連續的單引號或者雙引號(通常都是成對的用)。

例如:

#三引號

hi = '''hi

there'''

print hi

運行結果如下:

6

Unicode 字符串

Python 中定義一個 Unicode 字符串和定義一個普通字符串一樣簡單:

s2=u'Hello World !';

print s2引號前小寫的"u"表示這里創建的是一個 Unicode 字符串。如果你想加入一個特殊字符,可以使用 Python Unicode-Escape 編碼。如下例所示:

s3=u'Hello\u0020World !'

print s3

python的字符串內建函數

字符串方法是從python1.62.0慢慢加進來的——它們也被加到了Jython中。

這些方法實現了string模塊的大部分方法,如下表所示列出了目前字符串內建支持的方法,所有的方法都包含了對Unicode的支持,有一些甚至是專門用於Unicode的。

方法

描述

string.capitalize()

把字符串的第一個字符大寫

string.center(width)

返回一個原字符串居中,並使用空格填充至長度 width 的新字符串

string.count(str, beg=0, end=len(string))

返回 str string 里面出現的次數,如果 beg 或者 end 指定則返回指定范圍內 str 出現的次數

string.decode(encoding='UTF-8', errors='strict')

encoding 指定的編碼格式解碼 string,如果出錯默認報一個 ValueError errors 'ignore' 'replace'

string.encode(encoding='UTF-8', errors='strict')

encoding 指定的編碼格式編碼 string,如果出錯默認報一個ValueError 的異常,除非 errors 指定的是'ignore'或者'replace'

string.endswith(obj, beg=0, end=len(string))

檢查字符串是否以 obj 結束,如果beg 或者 end 指定則檢查指定的范圍內是否以 obj 結束,如果是,返回 True,否則返回 False.

string.expandtabs(tabsize=8)

把字符串 string 中的 tab 符號轉為空格,tab 符號默認的空格數是 8

string.find(str, beg=0, end=len(string))

檢測 str 是否包含在 string 中,如果 beg end 指定范圍,則檢查是否包含在指定范圍內,如果是返回開始的索引值,否則返回-1

string.index(str, beg=0, end=len(string))

find()方法一樣,只不過如果str不在 string中會報一個異常.

string.isalnum()

如果 string 至少有一個字符並且所有字符都是字母或數字則返

True,否則返回 False

string.isalpha()

如果 string 至少有一個字符並且所有字符都是字母則返回 True,

否則返回 False

string.isdecimal()

如果 string 只包含十進制數字則返回 True 否則返回 False.

string.isdigit()

如果 string 只包含數字則返回 True 否則返回 False.

string.islower()

如果 string 中包含至少一個區分大小寫的字符,並且所有這些(區分大小寫的)字符都是小寫,則返回 True,否則返回 False

string.isnumeric()

如果 string 中只包含數字字符,則返回 True,否則返回 False

string.isspace()

如果 string 中只包含空格,則返回 True,否則返回 False.

string.istitle()

如果 string 是標題化的( title())則返回 True,否則返回 False

string.isupper()

如果 string 中包含至少一個區分大小寫的字符,並且所有這些(區分大小寫的)字符都是大寫,則返回 True,否則返回 False

string.join(seq)

string 作為分隔符,將 seq 中所有的元素(的字符串表示)合並為一個新的字符串

string.ljust(width)

返回一個原字符串左對齊,並使用空格填充至長度 width 的新字符串

string.lower()

轉換 string 中所有大寫字符為小寫.

string.lstrip()

截掉 string 左邊的空格

string.maketrans(intab, outtab])

maketrans() 方法用於創建字符映射的轉換表,對於接受兩個參數的最簡單的調用方式,第一個參數是字符串,表示需要轉換的字符,第二個參數也是字符串表示轉換的目標。

max(str)

返回字符串 str 中最大的字母。

min(str)

返回字符串 str 中最小的字母。

string.partition(str)

有點像 find() split()的結合體, str 出現的第一個位置起, string 3 (string_pre_str,str,string_post_str),如果 string 中不包含str string_pre_str == string.

string.replace(str1, str2,  num=string.count(str1))

string 中的 str1 替換成 str2,如果 num 指定,則替換不超過 num .

string.rfind(str, beg=0,end=len(string) )

類似於 find()函數,不過是從右邊開始查找.

string.rindex( str, beg=0,end=len(string))

類似於 index(),不過是從右邊開始.

string.rjust(width)

返回一個原字符串右對齊,並使用空格填充至長度 width 的新字符串

string.rpartition(str)

類似於 partition()函數,不過是從右邊開始查找.

string.rstrip()

刪除 string 字符串末尾的空格.

string.split(str="", num=string.count(str))

str 為分隔符切片 string,如果 num有指定值,則僅分隔 num 個子字符串

string.splitlines(num=string.count('\n'))

按照行分隔,返回一個包含各行作為元素的列表,如果 num 指定則僅切片 num 個行.

string.startswith(obj, beg=0,end=len(string))

檢查字符串是否是以 obj 開頭,是則返回 True,否則返回 False。如果beg end 指定值,則在指定范圍內檢查.

string.strip([obj])

string 上執行 lstrip() rstrip()

string.swapcase()

翻轉 string 中的大小寫

string.title()

返回"標題化" string,就是說所有單詞都是以大寫開始,其余字母均為小寫( istitle())

string.translate(str, del="")

根據 str 給出的表(包含 256 個字符)轉換 string 的字符,

要過濾掉的字符放到 del 參數中

string.upper()

轉換 string 中的小寫字母為大寫

string.zfill(width)

返回長度為 width 的字符串,原字符串 string 右對齊,前面填充0

string.isdecimal()

isdecimal()方法檢查字符串是否只包含十進制字符。這種方法只存在於unicode對象。

 

2.3.2 列表

序列是Python中最基本的數據結構。序列中的每個元素都分配一個數字 - 它的位置,或索引,第一個索引是0,第二個索引是1,依此類推。

Python6個序列的內置類型,但最常見的是列表和元組。序列都可以進行的操作包括索引,切片,加,乘,檢查成員。此外,Python已經內置確定序列的長度以及確定最大和最小的元素的方法。列表是最常用的Python數據類型,它可以作為一個方括號內的逗號分隔值出現。列表的數據項不需要具有相同的類型

創建一個列表,只要把逗號分隔的不同的數據項使用方括號括起來即可。如下所示:

list1 =['physics','chemistry',1997,2000];

list2 =[1,2,3,4,5];

list3 =["a","b","c","d"];

與字符串的索引一樣,列表索引從0開始。列表可以進行截取、組合等。

訪問列表中的值

使用下標索引來訪問列表中的值,同樣你也可以使用方括號的形式截取字符,如下所示:

#!/usr/bin/python

 

list1 =['physics','chemistry',1997,2000];

list2 =[1,2,3,4,5,6,7];

 

print"list1[0]: ", list1[0]

print"list2[1:5]: ", list2[1:5]

運行結果如下:

7

 

更新列表

你可以對列表的數據項進行修改或更新,你也可以使用append()方法來添加列表項,如下所示:

#!/usr/bin/python

 

list =['physics','chemistry',1997,2000];

 

print"Value available at index 2 : "

print list[2];

list[2]=2001;

print"New value available at index 2 : "

print list[2];

運行結果如下:

8

 

刪除列表元素

可以使用 del 語句來刪除列表的的元素,如下所示:

#!/usr/bin/python

 

list1 =['physics','chemistry',1997,2000];

 

print list1;

del list1[2];

print"After deleting value at index 2 : "

print list1;

運行結果如下:

9

 

 

Python列表腳本操作符

列表對 + * 的操作符與字符串相似。+ 號用於組合列表,* 號用於重復列表。

如下所示:

Python 表達式

結果

描述

len([1, 2, 3])

3

長度

[1, 2, 3] + [4, 5, 6]

[1, 2, 3, 4, 5, 6]

組合

['Hi!'] * 4

['Hi!', 'Hi!', 'Hi!', 'Hi!']

重復

3 in [1, 2, 3]

True

元素是否存在於列表中

for x in [1, 2, 3]: print x,

1 2 3

迭代


Python列表截取

Python的列表截取與字符串操作類型,如下所示:

L =['spam','Spam','SPAM!']

操作:

Python 表達式

結果

描述

L[2]

'SPAM!'

讀取列表中第三個元素

L[-2]

'Spam'

讀取列表中倒數第二個元素

L[1:]

['Spam', 'SPAM!']

從第二個元素開始截取列表

 

Python列表函數&方法

Python包含以下函數:

序號

函數

1

cmp(list1, list2)
比較兩個列表的元素

2

len(list)
列表元素個數

3

max(list)
返回列表元素最大值

4

min(list)
返回列表元素最小值

5

list(seq)
將元組轉換為列表

Python包含以下方法:

序號

方法

1

list.append(obj)
在列表末尾添加新的對象

2

list.count(obj)
統計某個元素在列表中出現的次數

3

list.extend(seq)
在列表末尾一次性追加另一個序列中的多個值(用新列表擴展原來的列表)

4

list.index(obj)
從列表中找出某個值第一個匹配項的索引位置

5

list.insert(index, obj)
將對象插入列表

6

list.pop(obj=list[-1])
移除列表中的一個元素(默認最后一個元素),並且返回該元素的值

7

list.remove(obj)
移除列表中某個值的第一個匹配項

8

list.reverse()
反向列表中元素

9

list.sort([func])
對原列表進行排序

2.3.4 元組

Python的元組與列表類似,不同之處在於元組的元素不能修改。

元組使用小括號,列表使用方括號。

元組創建很簡單,只需要在括號中添加元素,並使用逗號隔開即可。

如下代碼:

tup1 = ('physics', 'chemistry', 1997, 2000);

tup2 = (1, 2, 3, 4, 5 );

tup3 = "a", "b", "c", "d";

創建空元組

tup1 = ();

元組中只包含一個元素時,需要在元素后面添加逗號

tup1 = (50,);

元組與字符串類似,下標索引從0開始,可以進行截取,組合等。

 

訪問元組

元組可以使用下標索引來訪問元組中的值,如下實例:

#!/usr/bin/python

 

tup1 = ('physics', 'chemistry', 1997, 2000);

tup2 = (1, 2, 3, 4, 5, 6, 7 );

 

print "tup1[0]: ", tup1[0]

print "tup2[1:5]: ", tup2[1:5]

運行結果如下

10

 

修改元組

元組中的元素值是不允許修改的,但我們可以對元組進行連接組合,如下實例:

#!/usr/bin/python

# -*- coding: UTF-8 -*-

 

tup1 = (12, 34.56);

tup2 = ('abc', 'xyz');

 

# 以下修改元組元素操作是非法的。

# tup1[0] = 100;

 

# 創建一個新的元組

tup3 = tup1 + tup2;

print tup3;

運行結果如下:

11

 

刪除元組

元組中的元素值是不允許刪除的,但我們可以使用del語句來刪除整個元組,如下實例:

#!/usr/bin/python

 

tup = ('physics', 'chemistry', 1997, 2000);

 

print tup;

del tup;

print "After deleting tup : "

print tup;

以上實例元組被刪除后,運行結果如下:

12

 

元組運算符

與字符串一樣,元組之間可以使用 + 號和 * 號進行運算。這就意味着他們可以組合和復制,運算后會生成一個新的元組。

Python 表達式

結果

描述

len((1, 2, 3))

3

計算元素個數

(1, 2, 3) + (4, 5, 6)

(1, 2, 3, 4, 5, 6)

連接

['Hi!'] * 4

['Hi!', 'Hi!', 'Hi!', 'Hi!']

復制

3 in (1, 2, 3)

True

元素是否存在

for x in (1, 2, 3): print x,

1 2 3

迭代


元組索引,截取

因為元組也是一個序列,所以我們可以訪問元組中的指定位置的元素,也可以截取索引中的一段元素,如下所示:

元組:

L = ('spam', 'Spam', 'SPAM!')

Python 表達式

結果

描述

L[2]

'SPAM!'

讀取第三個元素

L[-2]

'Spam'

反向讀取;讀取倒數第二個元素

L[1:]

('Spam', 'SPAM!')

截取元素


無關閉分隔符

任意無符號的對象,以逗號隔開,默認為元組,如下實例:

#!/usr/bin/python

 

print 'abc', -4.24e93, 18+6.6j, 'xyz';

x, y = 1, 2;

print "Value of x , y : ", x,y;

運行結果如下:

13

 

元組內置函數

Python元組包含了以下內置函數:

序號

方法及描述

1

cmp(tuple1, tuple2)
比較兩個元組元素。

2

len(tuple)
計算元組元素個數。

3

max(tuple)
返回元組中元素最大值。

4

min(tuple)
返回元組中元素最小值。

5

tuple(seq)
將列表轉換為元組。

 

2.3.5 字典

字典是另一種可變容器模型,且可存儲任意類型對象。

字典的每個鍵值(key=>value)對用冒號(:)分割,每個對之間用逗號(,)分割,整個字典包括在花括號({}) ,格式如下所示:

d ={key1 : value1, key2 : value2 }

鍵必須是唯一的,但值則不必。

值可以取任何數據類型,但鍵必須是不可變的,如字符串,數字或元組。

一個簡單的字典實例:

dict ={'Alice':'2341','Beth':'9102','Cecil':'3258'}

也可如此創建字典:

dict1 ={'abc':456};

dict2 ={'abc':123,98.6:37};

 

訪問字典里的值

把相應的鍵放入熟悉的方括弧,如下實例:

#!/usr/bin/python

 

dict ={'Name':'Zara','Age':7,'Class':'First'};

 

print"dict['Name']: ", dict['Name'];

print"dict['Age']: ", dict['Age'];

運行結果如下:

14

如果用字典里沒有的鍵訪問數據,會輸出錯誤:

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'};

 

print "dict['Name']: ", dict['Name'];

print "dict['Age']: ", dict['Age'];

print dict['Xuanhun']

運行結果如下:

15

修改字典

向字典添加新內容的方法是增加新的鍵/值對,修改或刪除已有鍵/值對如下實例:

#!/usr/bin/python

 

dict ={'Name':'Zara','Age':7,'Class':'First'};

 

dict['Age']=8;# update existing entry

dict['School']="DPS School";# Add new entry

 

 

print"dict['Age']: ", dict['Age'];

print"dict['School']: ", dict['School'];

運行結果如下

16

刪除字典元素

能刪單一的元素也能清空字典,清空只需一項操作。

顯示刪除一個字典用del命令,如下實例:

#!/usr/bin/python

# -*- coding: UTF-8 -*-

 

dict ={'Name':'Zara','Age':7,'Class':'First'};

 

del dict['Name'];# 刪除鍵是'Name'的條目

dict.clear();     # 清空詞典所有條目

del dict ;        # 刪除詞典

 

print"dict['Age']: ", dict['Age'];

print"dict['School']: ", dict['School'];

但這會引發一個異常,因為用del后字典不再存在:

17

字典鍵的特性

字典值可以沒有限制地取任何python對象,既可以是標准的對象,也可以是用戶定義的,但鍵不行。

兩個重要的點需要記住:

1)不允許同一個鍵出現兩次。創建時如果同一個鍵被賦值兩次,后一個值會被記住,如下實例:

#!/usr/bin/python

 

dict ={'Name':'Zara','Age':7,'Name':'Manni'};

 

print"dict['Name']: ", dict['Name'];

以上實例輸出結果:

dict['Name']:  Manni

2)鍵必須不可變,所以可以用數字,字符串或元組充當,所以用列表就不行,如下實例:

#!/usr/bin/python

 

dict ={['Name']:'Zara','Age':7};

print"dict['Name']: ", dict['Name'];

運行結果如下:

18

 

字典內置函數&方法

Python字典包含了以下內置函數:

序號

函數及描述

1

cmp(dict1, dict2)
比較兩個字典元素。

2

len(dict)
計算字典元素個數,即鍵的總數。

3

str(dict)
輸出字典可打印的字符串表示。

4

type(variable)
返回輸入的變量類型,如果變量是字典就返回字典類型。

Python字典包含了以下內置方法:

序號

函數及描述

1

radiansdict.clear()
刪除字典內所有元素

2

radiansdict.copy()
返回一個字典的淺復制

3

radiansdict.fromkeys()
創建一個新字典,以序列seq中元素做字典的鍵,val為字典所有鍵對應的初始值

4

radiansdict.get(key, default=None)
返回指定鍵的值,如果值不在字典中返回default

5

radiansdict.has_key(key)
如果鍵在字典dict里返回true,否則返回false

6

radiansdict.items()
以列表返回可遍歷的(, ) 元組數組

7

radiansdict.keys()
以列表返回一個字典所有的鍵

8

radiansdict.setdefault(key, default=None)
get()類似, 但如果鍵不存在於字典中,將會添加鍵並將值設為default

9

radiansdict.update(dict2)
把字典dict2的鍵/值對更新到dict

10

radiansdict.values()
以列表返回字典中的所有值

2.3.6 集合

把不同元素放在一起就組成了集合,集合的成員被稱為集合元素。Python的集合和數學的結合在概念和操作上基本相同。Python提供了兩種集合:可變集合和不可變集合。

創建集合

我們先看下面創建集合的代碼。

#!/usr/bin/python

# -*- coding: UTF-8 -*-

 

s1=set('abcdde')

s2=set([1,2,3,4,5])

s3 = frozenset("xuanhun")

 

print type(s1)

print type(s3)

print s2

運行結果如下:

19

訪問集合

由於集合本身是無序的,所以不能為集合創建索引或切片操作,只能循環遍歷或使用innot in來訪問或判斷集合元素。

接上面的代碼,添加一個循環輸出集合內容的代碼,如下所示。

20

從上圖的結果,我們可以看到集合無序,無重復元素的特性。

更新集合

可使用以下內建方法來更新(只有可變集合才能被更新):

s.add()
s.update()
s.remove()

下面的代碼測試了集合的添加和刪除操作:

s2=set([1,2,3,4,5])

print s2

s2.add("j")  

s2.remove(3)

print s2

運行結果如下:

21

聯合(|)

聯合(union)操作與集合的OR操作其實等價的,聯合符號有個等價的方法,union()

測試代碼如下:

s1=set('abcdde')

s2=set([1,2,3,4,5])

s4=s1|s2

print s4

運行結果如下:

22

交集(&)

與集合AND等價,交集符號的等價方法是intersection()

>>> s1&s2

set(['n'])

>>> s1.intersection(s2)

set(['n'])

 

差集

等價方法是difference()

>>> s1-s2

set(['i', 'b', 'e', 'g'])

>>> s1.difference(s2)

set(['i', 'b', 'e', 'g'])

 

2.3.7 小結

基本類型和和基本數據結構我們都介紹完畢了,是時候寫點更復雜的代碼了,下一節給大家介紹基本的條件判斷和循環。

 

2.4節《流程控制》已經在微信訂閱號搶先發布,心急的同學進入訂閱號(二維碼在下方),從菜單網絡安全”—>”Python黑帽編程進入即可。

本節視頻教程獲取方法,請掃描二維碼,在菜單網絡安全”——>”Python黑帽編程中找到對應的本文2.2.7節,有詳細方法。

 

由於教程仍在創作過程中,在整套教程完結前,感興趣的同學請關注我的微信訂閱號(xuanhun521,下方二維碼),我會第一時間在訂閱號推送圖文教程和視頻教程。問題討論請加qq群:Hacking 1群):303242737   Hacking 2群):147098303

 

關注之后,回復請回復“Python”,獲取更多內容。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM