正则表达式

引入标准库模块re

match() 和 search():查找到一个匹配后就停止
  • match(pattern, string, flags=0):从字符串开头开始匹配
# 做一次简单的文本匹配/搜索操作时:

# match():从字符串开头开始匹配,匹配失败时返回None
m = re.match('My', 'My name is xuebi')
print(m)
print(m.group())    # 匹配到的内容
print(m.start())    # 开始位置
print(m.end())    # 结束位置
print((m.start(), m.end()))    # (开始位置, 结束位置)
print(m.span())    # (开始位置, 结束位置)
# m.span() == (m.start(), m.end())

# <re.Match object; span=(0, 2), match='My'>
# My
# 0
# 2
# (0, 2)
# (0, 2)
# 做大量的匹配和搜索操作时:

# 编译(预编译模式):
# 功能上一样,执行速度更快
p = re.compile('[a-z]+')
m2 = p.match('aaaaMy name is xuebi')
m3 = p.match('xuebi is me')
print(m2)
print(m3)

if p.match('#xuebi is me'):
    print('yes')
else:
    print('no')

# <re.Match object; span=(0, 4), match='aaaa'>
# <re.Match object; span=(0, 5), match='xuebi'>
# no
  • search(pattern, string, flags=0):寻找首次匹配
m = re.search('xuebi', 'kele and xuebi are person? xubi is not.')    # 只找第一次出现的
print(m)
# —— <re.Match object; span=(9, 14), match='xuebi'>
findall() 和 finditer():查找字符串中所有的匹配项
# 预编译模式
text = 'Today is 2/12/2019. Python starts 23/10/2019. Yesterday is 1-12-2019.'
p = re.compile('\d+[-/]\d+[-/]\d')    # [-/]:要么-,要么/(-或/)
  • findall(pattern, string, flags=0):寻找所有匹配项,返回列表
lis = p.findall(text)
print(lis)
# ['2/12/2', '23/10/2', '1-12-2']
  • finditer(pattern, string, flags=0):寻找所有匹配项,返回迭代器对象
lis = p.finditer(text)
print(lis)
for item in lis:
    print(item)
    print(item.group())
# <callable_iterator object at 0x030CAC50>
# <re.Match object; span=(9, 15), match='2/12/2'>
# 2/12/2
# <re.Match object; span=(34, 41), match='23/10/2'>
# 23/10/2
# <re.Match object; span=(59, 65), match='1-12-2'>
# 1-12-2
  • split(pattern, string, maxsplit=0, flags=0)
msg = 'xuebi@qq.com'
lis = msg.split('@')
print(lis)
# —— ['xuebi', 'qq.com']

line = 'asdf fjdk;   afed,  fjek,asdf,   foo'
lis1 = re.split(r'[,;\s]+', line)    # 按逗号或分号或空白字符中一次或多次进行分割
lis2 = re.split(r'[,;\s]\s*', line)    # 按逗号或分号或空白字符且他们的后面再接0个或多个空白字符进行分割
print(lis1)    # 按原生字符串分割,\s匹配任意一个空白字符包括[ \t\n\r\f\v]
print(lis2)
# —— ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
# —— ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']

str.replace() 和 sub() 和 subn():

# 对于简单的替换,可以用str.replace()方法
text = 'yeah, but no, but yeah, but no, but yeah'
text = text.replace('yeah', 'yes')
print(text)
# —— yes, but no, but yes, but no, but yes
  • sub(pattern, repl, string, count=0, flags=0)
# 对于复杂的替换,可以用正则表达式中的sub()方法

# sub()替换匹配
p = re.compile(r'(\d+)/(\d+)/(\d+)')

text = 'Today is 12/2/2019. PyCon starts 10/23/2019.'
text = p.sub(r'\3-\1-\2', text)    # \3\2\1为group()对应的组元素
print(text)
# —— Today is 2019-12-2. PyCon starts 2019-10-23.

# 对于更复杂的替换,可以传递一个替换回调函数来代替。
# 一个替换回调函数的参数是一个Match对象,也就是match()或者find()返回的对象。
# 使用group()方法来提取特定的匹配部分。
# 回调函数最后返回替换字符串。

from calendar import month_abbr

def change_date(m):
    mon_name = month_abbr[int(m.group(1))]
    return '{} {} {}'.format(m.group(2), mon_name, m.group(3))

text = 'Today is 12/2/2019. PyCon starts 10/23/2019.'
text = p.sub(change_date, text)
print(text)
# —— Today is 2 Dec 2019. PyCon starts 23 Oct 2019.
  • subn(pattern, repl, string, count=0, flags=0)
# subn():可查出替换了多少次
newtext, n = p.subn(change_date, text)
print(newtext)
print(n)
# Today is 2 Dec 2019. PyCon starts 23 Oct 2019.
# 0

类似的还有:
fullmatch(pattern, string, flags=0)
compile(pattern, flags=0)
purge()
template(pattern, flags=0)
......

【拓展】回调函数
解决模块之间不能循环调用的问题

=================================

普通字符集


# 普通字符:普通的文本值代表自身,用于匹配非特殊字符
print(re.search('My', 'My name is xuebi'))    # My匹配My
# —— <re.Match object; span=(0, 2), match='My'>


# .:可匹配换行符\n以外的任意一个字符。
print(re.search('.', 'My name is xuebi'))    # 匹配一个非换行符
# —— <re.Match object; span=(0, 1), match='M'>

print(re.search('ab.', 'abCMy name is xuebi'))    # 匹配ab和一个非换行符
print(re.search('...', 'ab CMy name is xuebi'))    # 匹配三个非换行符
print(re.search('ab.', 'ab'))    # 匹配ab和一个非换行符
# —— <re.Match object; span=(0, 3), match='ab '>
# —— <re.Match object; span=(0, 3), match='ab '>
# —— None


# \:转义字符
print(re.search('xuebi.', 'xuebi.com'))    # 匹配xuebi和一个非换行字符
print(re.search('xuebi\.', 'xuebi.com'))    # 匹配xuebi和一个.字符
print(re.search('xuebi\.', 'xuebicom'))    # 匹配xuebi和一个.字符
# —— <re.Match object; span=(0, 6), match='xuebi.'>
# —— <re.Match object; span=(0, 6), match='xuebi.'>
# —— None


# []:匹配中括号内的一个字符(括号里内容不限)
# 1. 中括号内的字符可以全部列出,如[abc]表示匹配字符a或b或c
# 2. 也可以使用-表示范围,如[a-z]表示匹配所以小写字母中的任意一个字符
# 3. 本文后续要介绍的如*、+等特殊字符在中括号内将失去特殊含义,如[*+()]表示匹配字符*或+或(或)
# 4. 本文后续要介绍的特殊字符集如\d、\w等也可以放入此中括号内,继续保持特殊含义
# 5. 如果中括号内的字符序列前面有一个^,表示不匹配中括号内的任何一个字符,如[^0-9]表示不匹配数字,a[^0-9]c不匹配a1c,但会匹配abc
# 6. 要匹配字符],可以转义它,或者把它放在中括号内的首位,如a[()[\]{}]c或a[]()[{}]c都可以匹配到a]c
print(re.search('[abc]', 'a_xuebicom'))    # 匹配a或b或c
print(re.search('[a-z]', 'a_xuebicom'))    # 匹配a到z中任意一个
print(re.search('[*+()]', '(_xuebicom)'))    # 匹配字符 * 或 + 或 ( 或 )
print()
print(re.search('[^*+()]', '(_xuebicom)'))    # 匹配非字符 * 或 + 或 ( 或 )
print(re.search('[a[()[\]{}]]c', '(a]c_xuebicom)'))    # 匹配a或]或(或)或[或{或} 和 ]和c
# 等价于下一句
print(re.search('a[]()[{}]c', '(a]c_xuebicom)'))    # 匹配a 和]或(或)或[或{或} 和 c
# <re.Match object; span=(0, 1), match='a'>
# <re.Match object; span=(0, 1), match='a'>
# <re.Match object; span=(0, 1), match='('>
# 特殊字符集如\d、\w等例子请往下看
# <re.Match object; span=(1, 2), match='_'>
# <re.Match object; span=(1, 4), match='a]c'>
# <re.Match object; span=(1, 4), match='a]c'>

特殊字符集

# \d:匹配任意一个数字字符,等价于[0-9]
# \D:匹配任意一个非数字字符,等价于[^0-9]
# \s:匹配任意一个空白字符,等价于[ \t\n\r\f\v]
# \S:匹配任意一个非空字符,等价于[^ \t\n\r\f\v]
# \w:匹配任意一个alphanumeric character,等价于[a-zA-Z0-9_]
# \W:匹配任意一个non-alphanumeric character,等价于[^a-zA-Z0-9_]

print(re.search('a\db', 'xba1b)'))    # 匹配a和一个数字字符和b
# a\db == a[0-9]b
print(re.search('a\Db', 'xbaAb)'))    # 匹配a和一个非数字字符和b
# a\Db == a[^0-9]b
print(re.search('a\sb', 'xba b)'))    # 匹配a和一个空白字符和b
# a\sb == a[ \t\n\r\f\v]b
print(re.search('a\Sb', 'xbaCb)'))    # 匹配a和一个非空白字符和b
# a\Sb == a[^ \t\n\r\f\v]b
print(re.search('a\wb', 'xba_b)'))    # 匹配a和一个alphanumeric character和b
# a\wb == a[a-zA-Z0-9_]b
print(re.search('a\Wb', 'xba b)'))    # 匹配a和一个non-alphanumeric character和b
# a\Wb == a[^a-zA-Z0-9_]b
# <re.Match object; span=(2, 5), match='a1b'>
# <re.Match object; span=(2, 5), match='aAb'>
# <re.Match object; span=(2, 5), match='a b'>
# <re.Match object; span=(2, 5), match='aCb'>
# <re.Match object; span=(2, 5), match='a_b'>
# <re.Match object; span=(2, 5), match='a b'>

# 【例子】
import string
printable = string.printable
print(re.findall('\d', printable))
# ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
print(re.findall('\w', printable), end='')
# ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
# 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
# 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
# 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
# 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
# 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
# 'Y', 'Z', '_']
print(re.findall('\s', printable))
# [' ', '\t', '\n', '\r', '\x0b', '\x0c']

print(re.findall('\w', 'abc' + '-/*' + '\u00ea' + '\u0115'))
# ['a', 'b', 'c', 'ê', 'ĕ']

数量

# prev*      :匹配0个或多个prev,尽可能多地匹配,贪婪模式
# prev*?     :匹配0个或多个prev,尽可能少地匹配,非贪婪模式
# prev+      :匹配1个或多个prev,尽可能多地匹配,贪婪模式
# prev+?     :匹配1个或多个prev,尽可能少地匹配,非贪婪模式
# prev?      :匹配0个或多个prev,尽可能多地匹配,贪婪模式
# prev??     :匹配0个或多个prev,尽可能少地匹配,非贪婪模式
# prev{m}    :匹配m个连续的prev
# prev{m,n}  :匹配m个到n个连续的prev,尽可能多地匹配,贪婪模式
# prev{m,n}? :匹配m个到n个连续的prev,尽可能少地匹配,非贪婪模式

print(re.findall('ab*', 'ab'))
print(re.findall('ab*', 'a_ab_abbb'))
# ['ab']
# ['a', 'ab', 'abbb']
print(re.findall('ab*?', 'ab'))
print(re.findall('ab*?', 'a_ab_abbb'))
# ['a']
# ['a', 'a', 'a']
print(re.findall('ab+', 'abb'))
print(re.findall('ab+', 'a_ab_abbb'))
# ['abb']
# ['ab', 'abbb']
print(re.findall('ab+?', 'abb'))
print(re.findall('ab+?', 'a_ab_abbb'))
# ['ab']
# ['ab', 'ab']
print(re.findall('ab?', 'abb'))
print(re.findall('ab?', 'a_ab_abbb'))
# ['ab']
# ['a', 'ab', 'ab']
print(re.findall('ab??', 'abb'))
print(re.findall('ab??', 'a_ab_abbb'))
# ['a']
# ['a', 'a', 'a']
print(re.findall('a{3}', 'aaaa'))
print(re.findall('a{3}', 'a_aa_aaa'))
# ['aaa']
# ['aaa']
print(re.findall('a{1,3}', 'aaaaa'))
print(re.findall('a{1,3}', 'aaaaaaa'))
print(re.findall('a{1,3}', 'a_aa_aaa'))
# ['aaa', 'aa']
# ['aaa', 'aaa', 'a']
# ['a', 'aa', 'aaa']
print(re.findall('a{1,3}?', 'aa'))
print(re.findall('a{1,3}?', 'a_aa_aaa'))
# ['a', 'a']
# ['a', 'a', 'a', 'a', 'a', 'a']

# 可以在*或+或?的后面再添加一个?,此时表示非贪婪模式匹配,Python中的正则表达式默认是贪婪模式匹配,它会在满足整个表达式要求的前提下,尽可能多地去匹配字符

边界

# ^prev:匹配以prev开头的字符串
# prev$:匹配以prev结尾的字符串
# \b:单词边界。\b在Python中默认会被转义为\x08表示退格,需要将整个正则表达式指定为原始字符串(在前面加个r)
# \B:非单词边界
# \Aprev:匹配以prev开头的字符串
# prev\Z:匹配以prev结尾的字符串

print(re.findall('^ab_', 'ab_cd'))
print(re.findall('^.*_ab', '1+x_ab_cd_ab'))
# ['ab_']
# ['1+x_ab_cd_ab']
print(re.findall('_ab$', 'ab_cd_ab'))
print(re.findall('.*_ab$', '1+x_ab_cd_ab'))
# ['_ab']
# ['1+x_ab_cd_ab']
print(re.findall(r'\bfoo\b', ' foo foo.(foo)'))
print(re.findall(r'\bfoo\b', ' foobar _foo1'))
# ['foo', 'foo', 'foo']
# []
print(re.findall(r'py\B', 'pythonpy3py2'))
print(re.findall(r'py\B', 'py py.py!'))
# ['py', 'py', 'py']
# []
print(re.findall(r'\Aab', 'abcde'))
print(re.findall(r'\Aab', '_abcde'))
# ['ab']
print(re.findall(r'ab\Z', '123ab'))
print(re.findall(r'ab\Z', '123ab_'))
# ['ab']
# []

# 【例】
import re
s = 'I wish I may, I wish I might have a dish of fish tonight.'
m = re.search(r'(. dish\b).*(\bfish)', s)
print(m.group())
print(m.groups())
print(m.group(0))
print(m.group(1))
print(m.group(2))
# a dish of fish
# ('a dish', 'fish')
# a dish of fish
# a dish
# fish

分组

# (expr):将小括号内的表达式作为一个分组,后面可以接表示数量的特殊字符
# expr1|expr2:匹配expr1或expr2,等价于[expr1expr2]
# \1:引用编号为1的分组匹配到的字符串。类似的还有\0\2\3...
# (?P<NAME>expr):类似于(expr),同时给分组制定了一个别名NAME,注意时大写的字母P
# (?P=NAME):引用别名为NAME的分组,当然也可以继续使用编号形式引用分组,此时要加r制定为原始字符串。

print(re.findall('a(bc)?d', 'abcdd'))
print(re.findall('a(bc)?d', 'abcbcd'))
# ['bc']
# []
print(re.findall('p(i|u)g', 'pug_pig'))
# ['u', 'i']
print(re.findall(r'a(\d)b\1c\1d', 'a3b3c3d'))
# ['3']
print(re.findall(r'a(?P<quote>\d)b\1c(?P=quote)d', 'a3b3c3d'))
# ['3']

# 【例】
m2 = re.search(r'(?P<DISH>. dish\b).*(?P<FISH>\bfish)', s)
print(m2.groups())
print(m2.group())
print(m2.group('DISH'))
print(m2.group('FISH'))
print(m2.group(1))
print(m2.group(2))
# ('a dish', 'fish')
# a dish of fish
# a dish
# fish
# a dish
# fish

拓展语法

# (?:expr):非捕获组(成为整体但不成组)
# prev(?=next):环视,如果后面为next,则返回prev
# prev(?!next):环视,如果后面不是next,则返回prev
# (?<=prev)next:环视,如果前面为prev,则返回next
# (?<!\d)next:环视,如果前面不是prev,则返回next

print(re.findall('a(?:\d)+bc', 'a333bc'))
# print(re.findall(r'a(?:\d)+b\1c', 'a333bc'))    # 语法错误
# ['a333bc']
print(re.findall('ab(?=\d)', 'ab3_+'))    # ab后紧跟一个数字时,输出ab
# ['ab']
print(re.findall('ab(?!\d)', 'abc_+'))    # ab后紧跟一个非数字时,输出ab
# ['ab']
print(re.findall('(?<=\d)ab', '_+1ab'))    # ab前紧跟一个数字时,输出ab
# ['ab']
print(re.findall('(?<!\d)ab', '_+ab'))    # ab前紧跟一个非数字时,输出ab
# ['ab']

# 【例】
import re
line = 'asdf fjdk; afed, fjek,asdf, foo'
print(re.split(r'[;,\s]\s*', line))    # 使用多个分割符或者是分隔符周围不确定的空格时,来分割一个字符串
print(re.split(r'(;|,|\s)\s*', line))    # 使用括号时被匹配的文本(那些分隔符)也将出现在结果列表中
print(re.split(r'(?:,|;|\s)\s*', line))    # 不想保留分割字符串到结果列表中去,但仍然需要使用到括号来分组正则表达式的话, 确保你的分组是非捕获分组,形如(?:...)
# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
# ['asdf', ' ', 'fjdk', ';', 'afed', ',', 'fjek', ',', 'asdf', ',', 'foo']
# ['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']

实例1 — — 字符串忽略大小写的搜索替换

# 【实例1-1】为了在文本操作时忽略大小写,你需要在使用re模块的时候给这些操作提供re.IGNORECASE标志参数

import re
text = 'UPPER PYTHON, lower python, Mixed Python'
print(re.findall('python', text))
print(re.findall('python', text, flags=re.IGNORECASE))
print(re.sub('python', 'snake', text, flags=re.IGNORECASE))
# ['python']
# ['PYTHON', 'python', 'Python']
# UPPER snake, lower snake, Mixed snake

# 弊端:这样不管原字符串中的是大写、小写或首字母大写的python,全替换为小写的snake

# 【实例1-2】替换字符串能自动跟被匹配字符串的大小写保持一致
import re
text = 'UPPER PYTHON, lower python, Mixed Python'
def matchcase(word):
    def replace(m):
        text = m.group()
        if text.isupper():
            return word.upper()
        elif text.islower():
            return word.lower()
        elif text[0].isupper():
            return word.capitalize()
        else:
            return word
    return replace

print(re.sub('python', matchcase('snake'), text, flags=re.IGNORECASE))
# UPPER SNAKE, lower snake, Mixed Snake

# matchcase('snake')返回了一个回调函数

# 【拓展】Python支持的其它正则表达式的标志位flags:
# re.A: 或re.ASCII,使\w/\W/d/\D/\s/\S/\b/\B只匹配ASCII字符,不匹配Unicode字符。
# re.I: 或re.IGNORECASE,忽略大小写,[A-Z]会匹配小写字母。
# re.M: 或re.MULTILINE,多行模式,改变^或$的默认行为。
# re.S: 或re.DOTALL,Make the.special character match any character at all, including a newline; without this flag, .will match anything except a newline。
# re.U: 或re.UNICODE,默认使用此标志位,\w/\W/d/\D/\s/\S/\b/\B会匹配Unicode字符,如果指定了re.A标志,则re.U失效。
# re.X: 或re.VERBOSE,允许整个正则表达式写成多行,忽略空白字符,并可以添加#开头的注释,这样更美观。

# 【实例】
import re
a = re.compile(r"""\d +  # the integral part
                    \.    # the decimal point
                    \d *  # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")
print(a.match('10.2'))
print(b.match('10.2'))
# <re.Match object; span=(0, 4), match='10.2'>
# <re.Match object; span=(0, 4), match='10.2'>

# 【实例】一次指定多个标志位
import re
text = '''UPPER PYTHON
lower python
Mixed Python'''
print(re.sub('python$', 'snake', text))
# UPPER PYTHON
# lower python
# Mixed Python
print(re.sub('python$', 'snake', text, flags=re.IGNORECASE))
# UPPER PYTHON
# lower python
# Mixed snake
print(re.sub('python$', 'snake', text, flags=re.IGNORECASE|re.MULTILINE))
# UPPER snake
# lower snake
# Mixed snake
p = re.compile(r'python$', re.I|re.M)
print(p)
# re.compile('python$', re.IGNORECASE|re.MULTILINE)
print(p.sub('snake', text))
# UPPER snake
# lower snake
# Mixed snake
print(re.sub('(?im)python$', 'snake', text))
# UPPER snake
# lower snake
# Mixed snake

实例2 — — 最短匹配模式: 非贪婪

# 【实例2-1】试着用正则表达式匹配某个文本模式,但是它找到的是模式的最长可能匹配
import re
p = re.compile(r'"(.*)"')
text1 = 'Computer says "no."'
print(p.findall(text1))
text2 = 'Computer says "no." Phone says "yes."'
print(p.findall(text2))    # 默认是贪婪模式,(.*)会尽可能多的匹配,只要后面有一个"就能满足整个正则,所以匹配到最后一个冒号之前了
# ['no.']
# ['no." Phone says "yes.']

# 【实例2-2】修正2-1的问题在模式中的*操作符后面加上?修饰符
p2 = re.compile(r'"(.*?)"')
print(p2.findall(text2))
# ['no.', 'yes.']

实例3 — — 多行匹配

# 试着使用正则表达式去匹配一大块的文本,而你需要跨越多行去匹配,当你用点.去匹配任意字符的时候,忘记了点.不能匹配换行符\n的事实。
# 【实例3-1】试着去匹配C语言分割的注释
import re
text1 = '/* this is a comment */'
text2 = '''/* this is a
multiline comment */
'''
p = re.compile(r'/\*(.*?)\*/')
print(p.findall(text1))    # 能正确匹配单行
print(p.findall(text2))    # . 点号不能匹配多行中的换行符,所以整体匹配失败
# [' this is a comment ']
# []

# 【实例3-2】改进3-1,可以使用.|\n匹配所有字符,或者指定re.DOTALL标志位
p2 = re.compile(r'/\*((?:.|\n)*?)\*/')
print(p2.findall(text2))
p3 = re.compile(r'/\*(.*?)\*/', re.DOTALL)
print(p3)
print(p3.findall(text2))
# [' this is a\nmultiline comment ']
# re.compile('/\\*(.*?)\\*/', re.DOTALL)
# [' this is a\nmultiline comment ']

# 【例3-3】re.MULTILINE多行模式的用法

import re

text = 'This is some text -- with punctuation.\nA second line.'
pattern = r'(^\w+)|(\w+\S*$)'
single_line = re.compile(pattern)
multiline = re.compile(pattern, re.MULTILINE)

print('Single Line :')
for match in single_line.findall(text):
    print('  {!r}'.format(match))
print('Multline    :')
for match in multiline.findall(text):
    print('  {!r}'.format(match))

# Single Line :
#   ('This', '')
#   ('', 'line.')
# Multline    :
#   ('This', '')
#   ('', 'punctuation.')
#   ('A', '')
#   ('', 'line.')
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,884评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,212评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,351评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,412评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,438评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,127评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,714评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,636评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,173评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,264评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,402评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,073评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,763评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,253评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,382评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,749评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,403评论 2 358

推荐阅读更多精彩内容