摘要:插入符號匹配字符串的開頭,并且在模式也匹配換行后的首個符號。,和修飾符都是貪婪的它們在字符串進行盡可能多的匹配。如果正則式希望找到,它將會匹配整個字符串,而不僅是。用于表示一個字符集合。標記應該在表達式字符串首位表示。
re模塊和字符串處理
對于簡單的匹配,通常有str.find(),str.endswith(), str.startswith()
>>>text = "abcd" >>> text.startswith("a") True >>> text.startswith("b") False >>> text.endswith("d") True >>> text.find("c") 2 >>> text[2] "c"
對于比較復雜的匹配就需要用到正則表達式和re模塊了
>>> text1 = "4/24/2019" >>> text2 = "2019.4.24" >>> import re >>> re.match(r"d+/d+/d+", text1)#匹配成功 >>> re.match(r"d+/d+/d+", text2) #匹配失敗,沒有返回Mathch對象 #如果想用同一個模式匹配多個字符串,那么把模式字符串預編譯為模式對象 >>> c = re.compile(r"d+/d+/d+") >>> c re.compile("d+/d+/d+") >>> c.match(text1) #用編譯好的模式匹配字符串 #match總是從字符串開始處匹配,想查找字符串與模式匹配的所有位置用findall >>> text = "Today is 11/27/2012. PyCon starts 3/13/2013." >>> c.findall(text) #如果用match就會匹配失敗,因為它總是從開始第一個字母對比匹配 ["11/27/2012", "3/13/2013"]
在定義正則式的時候,通常會用括號去捕獲分組
>>> c = re.compile(r"(d+)/(d+)/(d+)") >>> m = c.match("4/24/2019") >>> m.group() #等于group(0) "4/24/2019" >>> m.group(0) #捕獲全部分組 "4/24/2019" >>> m.group(1) #捕獲第一個分組 "4" >>> m.groups() #捕獲所有分組,返回一個元組 ("4", "24", "2019") >>> text = "Today is 11/27/2012. PyCon starts 3/13/2013." >>> f = c.findall(text) #返回一個所有位置匹配成功的列表 >>> f [("11", "27", "2012"), ("3", "13", "2013")] >>> for month, day, year in c.findall(text): print("{}-{}-{}".format(year, month, day)) 2012-11-27 2013-3-13 #finditer()返回一個可迭代對象,每個元素都為一個Match對象 >>> c.finditer(text)>>> for i in c.finditer(text): ... print(i) >>> for i in c.finditer(text): print(i.group(3)) 2012 2013 >>> for i in c.finditer(text): print(i.groups()) ("11", "27", "2012") ("3", "13", "2013")
match()方法僅會匹配字符串開始處,能匹配到就返回匹配到的部分,如果想以正則表達式精確匹配整個字符串那么就要在正則表達式結尾加 $。
>>> c re.compile("(d+)/(d+)/(d+)") >>> m = c.match("11/27/2012abcdef") #此時把開頭匹配到的返回了 >>> m>>> m.group(0) "11/27/2012" >>> c = re.compile(r"(d+)/(d+)/(d+)$") #以 $ 結尾時只有匹配整個字符串才會匹配成功 >>> m = c.match("11/27/2012abcdef") >>> m #沒有值
但是需要注意的是,如果你打算做大量的匹配和搜索操作的話,最好先編譯正則表
達式,然后再重復使用它。模塊級別的函數會將最近編譯過的模式緩存起來,因此并
不會消耗太多的性能,但是如果使用預編譯模式的話,你將會減少查找和一些額外的
處理損耗**
對于簡單的字符串替換,一般用replace()即可
>>> t = "yes, no" >>> t.replace("yes", "no") "no, no"
對于復雜的模式。就需要用到re模塊的sub()函數
>>> text = "Today is 11/27/2012. PyCon starts 3/13/2013." >>> re.sub(r"(d+)/(d+)/(d+)", r"3-12-", text) "Today is 2012-1127-. PyCon starts 2013-313-." #sub()函數第一個參數是匹配模式,第二個參數是替換模式反斜杠加數字表示匹配捕獲的組號 #如果你打算用相同的模式做多次替換考慮先編譯它來提升性能比如: >>> import re >>> datepat = re.compile(r"(d+)/(d+)/(d+)") >>> datepat.sub(r"3-1-2", text) "Today is 2012-11-27. PyCon starts 2013-3-13."
以忽略大小寫的方式搜索與替換文本字符串
#為了在文本操作時忽略大小寫,你需要在使用 re 模塊的時候給這些操作提供re.IGNORECASE 標志參數。比如: >>> text = "UPPER PYTHON, lower python, Mixed Python" >>> re.findall("python", text, flags=re.IGNORECASE) ["PYTHON", "python", "Python"] >>> re.sub("python", "snake", text, flags=re.IGNORECASE) "UPPER snake, lower snake, Mixed snake"
非貪婪匹配
#這個問題一般出現在需要匹配一對分隔符之間的文本的時候 (比如引號包含的字符串)。 >>> c = re.compile(r""(.*)"") >>> c re.compile(""(.*)"") >>> text1 = "Computer says "no."" >>> c.findall(text1) ["no."] #正確匹配 >>> text2 = "Computer says "no." Phone says "yes."" >>> c.findall(text2) ["no." Phone says "yes."] #!這時應該匹配["no", "yes"] #在這個例子中,模式 r""(.*)"" 的意圖是匹配被雙引號包含的文本。但是在正則表達式中 * 操作符是貪婪的,因此匹配操作會查找最長的可能匹配。于是在第二個例子中搜索 text2 的時候返回結果并不是我們想要的。 #為了修正這個問題,可以在模式中的 * 操作符后面加上? 修飾符 >>> c = re.compile(r""(.*?)"") >>> c.findall(text2) ["no.", "yes."] #這樣就會使匹配變成非貪婪的
多行匹配換行符
# (.)不能匹配換行符 >>> comment = re.compile(r"/*(.*?)*/") #/*, /是轉義字符,匹配* >>> text1 = "/* this is a comment */" >>> text2 = """/* this is a ... multiline comment */ ... """ >>> >>> comment.findall(text1) [" this is a comment "] >>> comment.findall(text2) #(.)匹配除了換行的任意字符。如果指定了標簽 DOTALL ,它將匹配包括換行符的任意字符。此時字符串中間有換行符,匹配失敗 [] #re.compile() 函數接受一個標志參數叫 re.DOTALL ,在這里非常有用。它可以讓正則表達式中的點 (.) 匹配包括換行符在內的任意字符。比如: >>> comment = re.compile(r"/*(.*?)*/", re.DOTALL) >>> comment.findall(text2) [" this is a multiline comment "]
字符串對齊:format函數
#順便寫下來format吧。。 >>> format(text, ">20") " Hello World" >>> format(text, "<20") "Hello World " >>> format(text, "^20") " Hello World " >>> #如果你想指定一個非空格的填充字符,將它寫到對齊字符的前面即可 >>> format(text, "=>20s") "=========Hello World" >>> format(text, "*^20s") "****Hello World*****" #當格式化多個值的時候,這些格式代碼也可以被用在 format() 方法中 >>> "{:>10s} {:>10s}".format("Hello", "World") " Hello World" #format() 函數的一個好處是它不僅適用于字符串。它可以用來格式化任何值,使得它非常的通用 >>> x = 1.2345 >>> format(x, ">10") " 1.2345" >>> format(x, "^10.2f") " 1.23 "
當你想要拼接列表中的字符串和數字時,最有效的方法是生成器
>>> data = ["ACME", 50, 91.1] >>> ",".join(str(d) for d in data) "ACME,50,91.1
你想創建一個內嵌變量的字符串,變量被它的值所表示的字符串替換掉
#一般情況下可以用format來實現 >>> s = "{name} has {n} messages." >>> s.format(name="Guido", n=37) "Guido has 37 messages." #如果要被替換的變量能在變量域中找到,那么你可以結合使用 format map()和 vars() >>> name = "yang" >>> n = 21 >>> s.format_map(vars()) "yang has 21 messages."
.
(點) 在默認模式,匹配除了換行的任意字符。如果指定了標簽 DOTALL ,它將匹配包括換行符的任意字符。
^
(插入符號) 匹配字符串的開頭, 并且在 MULTILINE 模式也匹配換行后的首個符號。
$
匹配字符串尾或者換行符的前一個字符,在 MULTILINE 模式匹配換行符的前一個字符。 foo 匹配 "foo" 和 "foobar" , 但正則 foo$ 只匹配 "foo"。更有趣的是, 在 "foo1
foo2
" 搜索 foo.$ ,通常匹配 "foo2" ,但在 MULTILINE 模式 ,可以匹配到 "foo1" ;在 "foon" 搜索 $ 會找到兩個空串:一個在換行前,一個在字符串最后。
*
對它前面的正則式匹配0到任意次重復, 盡量多的匹配字符串。 ab* 會匹配 "a", "ab", 或者 "a"后面跟隨任意個 "b"。
+
對它前面的正則式匹配1到任意次重復。 ab+ 會匹配 "a" 后面跟隨1個以上到任意個 "b",它不會匹配 "a"。
?
對它前面的正則式匹配0到1次重復。 ab? 會匹配 "a" 或者 "ab"。
*?, +?, ??
"", "+",和 "?" 修飾符都是 貪婪的;它們在字符串進行盡可能多的匹配。有時候并不需要這種行為。如果正則式 <.> 希望找到 " b
"{m}"
對其之前的正則式指定匹配 m 個重復;少于 m 的話就會導致匹配失敗。比如, a{6} 將匹配6個 "a" , 但是不能是5個。
"{m, n}"
對正則式進行 m 到 n 次匹配,在 m 和 n 之間取盡量多。 比如,a{3,5} 將匹配 3 到 5個 "a"。忽略 m 意為指定下界為0,忽略 n 指定上界為無限次。 比如 a{4,}b 將匹配 "aaaab" 或者1000個 "a" 尾隨一個 "b",但不能匹配 "aaab"。逗號不能省略,否則無法辨別修飾符應該忽略哪個邊界。
{m,n}?
前一個修飾符的非貪婪模式,只匹配盡量少的字符次數。比如,對于 "aaaaaa", a{3,5} 匹配 5個 "a" ,而 a{3,5}? 只匹配3個 "a"。
轉義特殊字符(允許你匹配 "*", "?", 或者此類其他),或者表示一個特殊序列;特殊序列之后進行討論。 如果你沒有使用原始字符串( r"raw" )來表達樣式,要牢記Python也使用反斜杠作為轉義序列;如果轉義序列不被Python的分析器識別,反斜杠和字符才能出現在字符串中。如果Python可以識別這個序列,那么反斜杠就應該重復兩次。這將導致理解障礙,所以高度推薦,就算是最簡單的表達式,也要使用原始字符串。
[]
用于表示一個字符集合。在一個集合中: 字符可以多帶帶列出,比如 [amk] 匹配 "a", "m", 或者 "k"。 可以表示字符范圍,通過用 "-" 將兩個字符連起來。比如 [a-z] 將匹配任何小寫ASCII字符, 0-5 將匹配從 00 到 59 的兩位數字, [0-9A-Fa-f] 將匹配任何十六進制數位。 如果 - 進行了轉義 (比如 [a-z])或者它的位置在首位或者末尾(如 [-a] 或 [a-]),它就只表示普通字符 "-"。 特殊字符在集合中,失去它的特殊含義。比如 [(+)] 只會匹配這幾個文法字符 "(", "+", "", or ")"。 字符類如 w 或者 S (如下定義) 在集合內可以接受,它們可以匹配的字符由 ASCII 或者 LOCALE 模式決定。 不在集合范圍內的字符可以通過 取反 來進行匹配。如果集合首字符是 "^" ,所有 不 在集合內的字符將會被匹配,比如 1 將匹配所有字符,除了 "5", 2 將匹配所有字符,除了 "^". ^ 如果不在集合首位,就沒有特殊含義。 在集合內要匹配一個字符 "]",有兩種方法,要么就在它之前加上反斜杠,要么就把它放到集合首位。比如, [()[]{}] 和 []()[{}] 都可以匹配括號。 Unicode Technical Standard #18 里的嵌套集合和集合操作支持可能在未來添加。這將會改變語法,所以為了幫助這個改變,一個 FutureWarning 將會在有多義的情況里被 raise,包含以下幾種情況,集合由 "[" 開始,或者包含下列字符序列 "--", "&&", "~~", 和 "||"。為了避免警告,需要將它們用反斜杠轉義。 在 3.7 版更改: 如果一個字符串構建的語義在未來會改變的話,一個 FutureWarning 會 raise 。
|
A|B, A 和 B 可以是任意正則表達式,創建一個正則表達式,匹配 A 或者 B. 任意個正則表達式可以用 "|" 連接。它也可以在組合(見下列)內使用。掃描目標字符串時, "|" 分隔開的正則樣式從左到右進行匹配。當一個樣式完全匹配時,這個分支就被接受。意思就是,一旦 A 匹配成功, B 就不再進行匹配,即便它能產生一個更好的匹配。或者說,"|" 操作符絕不貪婪。 如果要匹配 "|" 字符,使用 |, 或者把它包含在字符集里,比如 [|].
(...)
(組合),匹配括號內的任意正則表達式,并標識出組合的開始和結尾。匹配完成后,組合的內容可以被獲取,并可以在之后用 number 轉義序列進行再次匹配,之后進行詳細說明。要匹配字符 "(" 或者 ")", 用 ( 或 ), 或者把它們包含在字符集合里: [(], [)].
(?…)
這是個擴展標記法 (一個 "?" 跟隨 "(" 并無含義)。 "?" 后面的第一個字符決定了這個構建采用什么樣的語法。這種擴展通常并不創建新的組合; (?P
(?aiLmsux)
( "a", "i", "L", "m", "s", "u", "x" 中的一個或多個) 這個組合匹配一個空字符串;這些字符對正則表達式設置以下標記 re.A (只匹配ASCII字符), re.I (忽略大小寫), re.L (語言依賴), re.M (多行模式), re.S (點dot匹配全部字符), re.U (Unicode匹配), and re.X (冗長模式)。 (這些標記在 模塊內容 中描述) 如果你想將這些標記包含在正則表達式中,這個方法就很有用,免去了在 re.compile() 中傳遞 flag 參數。標記應該在表達式字符串首位表示。
(?:…)
正則括號的非捕獲版本。 匹配在括號內的任何正則表達式,但該分組所匹配的子字符串 不能 在執行匹配后被獲取或是之后在模式中被引用。
(?aiLmsux-imsx:…)
("a", "i", "L", "m", "s", "u", "x" 中的0或者多個, 之后可選跟隨 "-" 在后面跟隨 "i" , "m" , "s" , "x" 中的一到多個 .) 這些字符為表達式的其中一部分 設置 或者 去除 相應標記 re.A (只匹配ASCII), re.I (忽略大小寫), re.L (語言依賴), re.M (多行), re.S (點匹配所有字符), re.U (Unicode匹配), and re.X (冗長模式)。(標記描述在 模塊內容 .) "a", "L" and "u" 作為內聯標記是相互排斥的, 所以它們不能結合在一起,或者跟隨 "-" 。 當他們中的某個出現在內聯組中,它就覆蓋了括號組內的匹配模式。在Unicode樣式中, (?a:...) 切換為 只匹配ASCII, (?u:...) 切換為Unicode匹配 (默認). 在byte樣式中 (?L:...) 切換為語言依賴模式, (?a:...) 切換為 只匹配ASCII (默認)。這種方式只覆蓋組合內匹配,括號外的匹配模式不受影響。 3.6 新版功能. 在 3.7 版更改: 符號 "a", "L" 和 "u" 同樣可以用在一個組合內。
(?P
(命名組合)類似正則組合,但是匹配到的子串組在外部是通過定義的 name 來獲取的。組合名必須是有效的Python標識符,并且每個組合名只能用一個正則表達式定義,只能定義一次。一個符號組合同樣是一個數字組合,就像這個組合沒有被命名一樣。 命名組合可以在三種上下文中引用。如果樣式是 (?P[""]).*?(?P=quote) (也就是說,匹配單引號或者雙引號括起來的字符串): 引用組合 "quote" 的上下文 引用方法 在正則式自身內 (?P=quote) (如示) 1 處理匹配對象 m m.group("quote") m.end("quote") (等) 傳遞到 re.sub() 里的 repl 參數中 g
g<1> 1
(?P=name)
反向引用一個命名組合;它匹配前面那個叫 name 的命名組中匹配到的串同樣的字串。
(?#…)
注釋;里面的內容會被忽略。
(?=…)
匹配 … 的內容,但是并不消費樣式的內容。這個叫做 lookahead assertion。比如, Isaac (?=Asimov) 匹配 "Isaac " 只有在后面是 "Asimov" 的時候。
(?!…)
匹配 … 不符合的情況。這個叫 negative lookahead assertion (前視取反)。比如說, Isaac (?!Asimov) 只有后面 不 是 "Asimov" 的時候才匹配 "Isaac " 。
(?<=…)
匹配字符串的當前位置,它的前面匹配 … 的內容到當前位置。這叫:dfn:positive lookbehind assertion (正向后視斷定)。 (?<=abc)def 會在 "abcdef" 中找到一個匹配,因為后視會往后看3個字符并檢查是否包含匹配的樣式。包含的匹配樣式必須是定長的,意思就是 abc 或 a|b 是允許的,但是 a* 和 a{3,4} 不可以。注意以 positive lookbehind assertions 開始的樣式,如 (?<=abc)def ,并不是從 a 開始搜索,而是從 d 往回看的。你可能更加愿意使用 search() 函數,而不是 match() 函數: >>> import re >>> m = re.search("(?<=abc)def", "abcdef") >>> m.group(0) "def" 這個例子搜索一個跟隨在連字符后的單詞: >>> m = re.search(r"(?<=-)w+", "spam-egg") >>> m.group(0) "egg" 在 3.5 版更改: 添加定長組合引用的支持。
(?匹配當前位置之前不是 … 的樣式。這個叫:dfn:negative lookbehind assertion (后視斷定取非)。類似正向后視斷定,包含的樣式匹配必須是定長的。由 negative lookbehind assertion 開始的樣式可以從字符串搜索開始的位置進行匹配。
(?(id/name)yes-pattern|no-pattern)
如果給定的 id 或 name 存在,將會嘗試匹配 yes-pattern ,否則就嘗試匹配 no-pattern,no-pattern 可選,也可以被忽略。比如, (<)?(w+@w+(?:.w+)+)(?(1)>|$) 是一個email樣式匹配,將匹配 "
由 "" 和一個字符組成的特殊序列在以下列出。 如果普通字符不是ASCII數位或者ASCII字母,那么正則樣式將匹配第二個字符。比如,$ 匹配字符 "$".
number
匹配數字代表的組合。每個括號是一個組合,組合從1開始編號。比如 (.+) 1 匹配 "the the" 或者 "55 55", 但不會匹配 "thethe" (注意組合后面的空格)。這個特殊序列只能用于匹配前面99個組合。如果 number 的第一個數位是0, 或者 number 是三個八進制數,它將不會被看作是一個組合,而是八進制的數字值。在 "[" 和 "]" 字符集合內,任何數字轉義都被看作是字符。
A
只匹配字符串開始。
b
匹配空字符串,但只在單詞開始或結尾的位置。一個單詞被定義為一個單詞字符的序列。注意,通常 b 定義為 w 和 W 字符之間,或者 w 和字符串開始/結尾的邊界, 意思就是 r"bfoob" 匹配 "foo", "foo.", "(foo)", "bar foo baz" 但不匹配 "foobar" 或者 "foo3"。 默認情況下,Unicode字母和數字是在Unicode樣式中使用的,但是可以用 ASCII 標記來更改。如果 LOCALE 標記被設置的話,詞的邊界是由當前語言區域設置決定的,b 表示退格字符,以便與Python字符串文本兼容。
B
匹配空字符串,但 不 能在詞的開頭或者結尾。意思就是 r"pyB" 匹配 "python", "py3", "py2", 但不匹配 "py", "py.", 或者 "py!". B 是 b 的取非,所以Unicode樣式的詞語是由Unicode字母,數字或下劃線構成的,雖然可以用 ASCII 標志來改變。如果使用了 LOCALE 標志,則詞的邊界由當前語言區域設置。
d
對于 Unicode (str) 樣式: 匹配任何Unicode十進制數(就是在Unicode字符目錄[Nd]里的字符)。這包括了 [0-9] ,和很多其他的數字字符。如果設置了 ASCII 標志,就只匹配 [0-9] 。 對于8位(bytes)樣式: 匹配任何十進制數,就是 [0-9]。
D
匹配任何非十進制數字的字符。就是 d 取非。 如果設置了 ASCII 標志,就相當于 3 。
s
對于 Unicode (str) 樣式: 匹配任何Unicode空白字符(包括 [ tnrfv] ,還有很多其他字符,比如不同語言排版規則約定的不換行空格)。如果 ASCII 被設置,就只匹配 [ tnrfv] 。 對于8位(bytes)樣式: 匹配ASCII中的空白字符,就是 [ tnrfv] 。
S
匹配任何非空白字符。就是 s 取非。如果設置了 ASCII 標志,就相當于 4 。
w
對于 Unicode (str) 樣式: 匹配Unicode詞語的字符,包含了可以構成詞語的絕大部分字符,也包括數字和下劃線。如果設置了 ASCII 標志,就只匹配 [a-zA-Z0-9_] 。 對于8位(bytes)樣式: 匹配ASCII字符中的數字和字母和下劃線,就是 [a-zA-Z0-9_] 。如果設置了 LOCALE 標記,就匹配當前語言區域的數字和字母和下劃線。
W
匹配任何非詞語字符。是 w 取非。如果設置了 ASCII 標記,就相當于 5 。如果設置了 LOCALE 標志,就匹配當前語言區域的 非 詞語字符。
Z
只匹配字符串尾。
絕大部分Python的標準轉義字符也被正則表達式分析器支持。:
a f u U v x
(注意 b 被用于表示詞語的邊界,它只在字符集合內表示退格,比如 [b] 。)
"u" 和 "U" 轉義序列只在 Unicode 樣式中支持。 在 bytes 算啊看會顯示錯誤。 未知的 ASCII 字符轉義序列保留在未來使用,會被當作錯誤來處理。
八進制轉義包含為一個有限形式。如果首位數字是 0, 或者有三個八進制數位,那么就認為它是八進制轉義。其他的情況,就看作是組引用。對于字符串文本,八進制轉義最多有三個數位長。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/43936.html
摘要:今天來給大家分享一份關于比較詳細的正則表達式寶典,學會之后你將對正則表達式達到精通的狀態。正則表達式是用在方法當中,大多數的字符串檢索都可以通過來完成。導入模塊在使用正則表達式之前,需要導入模塊。 ...
摘要:假設現在想把字符串你好,,世界中的中文提取出來,可以這么做你好,,世界注意到,我們在正則表達式前面加上了兩個前綴,其中表示使用原始字符串,表示是字符串。本文標題為正則表達式模塊簡明筆記本文鏈接為參考資料正則表達式 簡介 正則表達式(regular expression)是可以匹配文本片段的模式。最簡單的正則表達式就是普通字符串,可以匹配其自身。比如,正則表達式 hello 可以匹配字符...
摘要:多行模式,改變元字符和的行為。模塊級方法編譯正則表達式,返回一個對象。掃描參數,查找正則表達式產生匹配的第一個結果,返回一個對象。清空正則表達式緩存。和參數意義同與模塊級的相同與模塊級的相同屬性返回一個正整數,表示正則匹配模式。 匹配模式 re.ASCII同re.A,對應的內聯標識為(?a),用于向后兼容。使元字符w, W, , B, d, D, s和S僅匹配ASCII字符。該模式只...
摘要:項目的一個需求是解析的日志文件。項目中已經按照業務規則對日志文件進行了處理命名規則如下并且所有的日志文件存放在統一路徑下。模塊使用緩存,所以會耗費內存,耗費量與要解析的文件相關。剩下的工作就是根據業務需要,對獲得的基本信息進行處理。 項目的一個需求是解析nginx的日志文件。 簡單的整理如下: 日志規則描述 首先要明確自己的Nginx的日志格式,這里采用默認Nginx日志格式: ...
摘要:項目的一個需求是解析的日志文件。項目中已經按照業務規則對日志文件進行了處理命名規則如下并且所有的日志文件存放在統一路徑下。模塊使用緩存,所以會耗費內存,耗費量與要解析的文件相關。剩下的工作就是根據業務需要,對獲得的基本信息進行處理。 項目的一個需求是解析nginx的日志文件。 簡單的整理如下: 日志規則描述 首先要明確自己的Nginx的日志格式,這里采用默認Nginx日志格式: ...
閱讀 1554·2021-11-19 09:55
閱讀 2778·2021-09-06 15:02
閱讀 3534·2019-08-30 15:53
閱讀 1071·2019-08-29 16:36
閱讀 1230·2019-08-29 16:29
閱讀 2286·2019-08-29 15:21
閱讀 621·2019-08-29 13:45
閱讀 2679·2019-08-26 17:15