python基础知识2(模块)

模块

定义:用来从逻辑上组织python代码(变量,函数,累,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py对用的模块名:test)

导入方法

import module_name
import module1_name,module2_name
from module_file import *
from module_file import module1_name,module2_name
from module_file import module_name as mn

import本质(路径搜索和搜索路径)

导入模块的本质就是把python文件解释一遍
导入包的本质就是解释包下面的init.py文件
包的本质:用来从逻辑上组织模块,本质就是一个目录(必须带有一个init.py文件)
如果要导入包下面的模块文件,就要修改init.py文件,在里面导入模块文件

模块的分类

标准库

time、datetime模块

python中,通常有这几种方式表示时间:

  • 时间戳
  • 格式化的时间字符串
  • 元组(struct_time)共九个元素

时间戳:
表示从1970年1月1日00:00开始按秒计算偏移量,运行‘type(time.time())’,返回的是float类型,返回时间戳方式的函数主要有time()

元组(struct_time):
struct_time元组共有9个元素,返回struct_time的函数主要有gmtime()、localtime()、strptime()

time

import time

print(time.time())#得到当前时间的时间戳
#输出:1565966794.21425
print(time.timezone)#utc时间与本地时间的差值(时间戳)
#输出:-28800
print(time.altzone)#utc时间与夏令时间的差值(时间戳)
#输出:-32400
print(time.localtime())#返回本地时间的struct_time对象格式
#输出:time.struct_time(tm_year=2019, tm_mon=8, tm_mday=16, tm_hour=22, tm_min=53, tm_sec=29, tm_wday=4, tm_yday=228, tm_isdst=0)
print(time.gmtime())#返回utc时间的struct_time对象格式
#输出:time.struct_time(tm_year=2019, tm_mon=8, tm_mday=16, tm_hour=14, tm_min=58, tm_sec=3, tm_wday=4, tm_yday=228, tm_isdst=0)
print(time.asctime())#将struct_time对象格式转换成本地时间格式:Fri Aug 16 23:00:14 2019
#输出:Fri Aug 16 23:00:14 2019
print(time.ctime())#将时间戳转换成本地时间格式:Fri Aug 16 23:00:14 2019
#输出:Fri Aug 16 23:00:14 2019
string_struct=time.strptime('2019/8/16 23:04','%Y/%m/%d %H:%M')#将日期字符串转成struct时间对象格式
print(string_struct)
#输出:time.struct_time(tm_year=2019, tm_mon=8, tm_mday=16, tm_hour=23, tm_min=4, tm_sec=0, tm_wday=4, tm_yday=228, tm_isdst=-1)
print(time.strftime('%Y/%m/%d %H:%M',string_struct))#将struct时间对象转成日期字符串
#输出:2019/08/16 23:04
print(time.mktime(string_struct))#将struct时间对象转成时间戳
#输出:1565967840.0

struct_time和时间戳<->时间字符串格式的转换:

image.png

格式化的时间字符串<->struct_time<->时间戳 的相互转换
image.png

datetime

import datetime

print(datetime.datetime.now())#返回格式化日期格式
#输出:2019-08-17 00:32:25.011494
print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
#输出:2019-08-20 00:32:25.011494
print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
#输出:2019-08-14 00:32:25.011494
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
#输出:2019-08-17 03:32:25.011494
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
#输出:2019-08-17 01:02:25.011494
c_time  = datetime.datetime.now()
print(c_time.replace(minute=3,hour=2))#时间替换,将小时替换为2,分钟变为3
#输出:2019-08-17 02:03:25.011494

random模块

import random

print(random.random())#取0-1的随机浮点数
#输出:0.07306541518636855
print(random.randint(1,3))#取[1,3]闭区间的整数
print(random.randrange(1,3))#取[1,3)半闭半开区间的整数
print(random.choice('abcde'))#随机取字符串中的字符
print(random.choice([1,2,3,4,5,6]))#随机取列表中的数据
print(random.sample('abcde',2))#随机取两位数据
#输出:['b', 'e']
print(random.uniform(1,3))#取(1,3)区间的浮点数
#输出:2.1186016630230196
a=[1,2,3,4,5,6]
random.shuffle(a)#随机打乱数据顺序
print(a)
#输出:[3, 1, 5, 6, 2, 4]

生成随机验证码:

checkcode = ''
for i in range(6):
    b_current = random.randrange(0,6)
    if b_current != i:
        s_current=random.randrange(0,6)
        if s_current==b_current:
            temp = chr(random.randint(97,122))
        else:
            temp = chr(random.randint(65,90))
    else:
        temp = random.randint(0,9)
    checkcode += str(temp)
print (checkcode)

os模块

import os

print(os.getcwd())#获取当前工作目录,即当前python脚本工作的目录路径
os.chdir('C://')#改变当前脚本工作目录;相当于shell下cd
print(os.curdir)#返回当前目录: ('.')
print(os.pardir)#获取当前目录的父目录字符串名:('..')
os.makedirs(r'd:\a\b\c')#可生成多层递归目录
os.removedirs(r'd:\a\b\c')#若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir(r'd:a')#生成单级目录;相当于shell中mkdir dirname
os.rmdir(r'd:a')# 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
print(os.listdir(r'd:'))#列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
#输出:['$360Section', '$RECYCLE.BIN', '360Downloads', '360Rec', '360安全浏览器下载', 'BaiduNetdiskDownload', 'computer software', 'Config.Msi']
os.remove(r'd:\a')#删除一个文件
os.rename(r'd:\a',r'd:\b')#重命名文件/目录
print(os.stat(r'd:360安全浏览器下载'))#获取文件/目录信息
#输出:os.stat_result(st_mode=16895, st_ino=5066549580791849, st_dev=485194, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1565493157, st_mtime=1565493157, st_ctime=1563296312)
print(os.environ)#当前系统的环境变量
print(os.name)#输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system('dir')#运行shell命令,直接显示
print(os.path.abspath('./'))#返回path规范化的绝对路径
print(os.path.split(r'd:a.txt'))#将path分割成目录和文件名二元组返回
#输出:('d:', 'a.txt')
print(os.path.dirname(os.path.abspath('./')))#返回path的目录。其实就是os.path.split(path)的第一个元素
print(os.path.basename(os.path.abspath('./')))#返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
print(os.path.exists(os.path.abspath('./')))#判断路径是否存在,如果path存在,返回True;如果path不存在,返回False
print(os.path.isabs(os.path.abspath('./')))#判断路径是否是绝对路径
print(os.path.isfile(os.path.abspath('./')))#判断路径是否是文件
print(os.path.isdir(os.path.abspath('./')))#判断路径是否是目录
print(os.path.join(r'dir\haha',r'module',r'file'))#将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
#输出:dir\haha\module\file
import time
struct_time=time.localtime(os.path.getatime(os.path.abspath('./')))
print(time.strftime('%Y-%m-%d %H:%M:%S',struct_time))#返回path所指向的文件或者目录的最后存取时间,结果是时间戳,这里转化为字符串时间格式
#输出:2019-08-18 15:53:13
print(os.path.getmtime(os.path.abspath('./')))#返回path所指向的文件或者目录的最后修改时间
#输出:1566114793.5133495
print(os.sep)#输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
print(os.linesep)#输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n"
print(os.pathsep)#输出用于分割文件路径的字符串

具体实现如下图:


image.png

sys模块

#sys_module.py文件
import sys
print(sys.argv)#命令行参数List,第一个元素是程序本身路径

#cmd命令运行 并带上参数
E:\test\pycharm\file\python develop\day5>python sys_module.py 1 2 3 4 5
['sys_module.py', '1', '2', '3', '4', '5']
print(sys.version)#获取Python解释程序的版本信息
#输出:3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)]
print(sys.path)#返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
print(sys.platform)#返回操作系统平台名称
sys.exit(0)#退出程序,正常退出时exit(0)

shutil模块

高级的 文件、文件夹、压缩包 处理模块

copyfileobj将文件内容拷贝到另一个文件中,可以部分内容

f1=open('buweixia',encoding='utf-8')
f2=open('buweixia2','w',encoding='utf-8')
shutil.copyfileobj(f1,f2)

copyfile拷贝文件,自动打开文件

shutil.copyfile('buweixia2','buweixia3')

copystat拷贝状态的信息,包括:mode bits, atime, mtime, flags

import os
print(os.stat('buweixia2'))
shutil.copystat('buweixia2','buweixia3')
print(os.stat('buweixia3'))
#输出:
# os.stat_result(st_mode=33206, st_ino=1688849860284406, st_dev=508939, st_nlink=1, st_uid=0, st_gid=0, st_size=1785, st_atime=1566120930, st_mtime=1566121662, st_ctime=1566120930)
# os.stat_result(st_mode=33206, st_ino=2251799813705719, st_dev=508939, st_nlink=1, st_uid=0, st_gid=0, st_size=1785, st_atime=1566120930, st_mtime=1566121662, st_ctime=1566121586)

copy拷贝文件和权限

shutil.copy('buweixia3','buweixia4')

copy2拷贝文件和状态信息

shutil.copy2('buweixia3','buweixia5')

copytree递归的去拷贝文件

shutil.copytree('./copy_file','./haha')
image.png

rmtree递归的去删除文件

shutil.rmtree('./copy_file')

move递归的去移动文件,且可以重命名目录

shutil.move('./enen', './copy_file')

make_archive创建压缩包并返回文件路径,例如:zip、tar

  • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
    如:www =>保存至当前路径
    如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
  • format:压缩包种类,“zip”, “tar”, “bztar”,“gztar”
  • root_dir:要压缩的文件夹路径(默认当前目录)
  • owner:用户,默认当前用户
  • group: 组,默认当前组
  • logger:用于记录日志,通常是logging.Logger对象
shutil.make_archive('./tar_file','tar')

shelve模块

将数据写入文件:

import shelve
info={'age':24,'sex':'m'}
name=['haha','enen','yoyo']
test=(1,2,3,4)
f['test']=test
f['name']=name
f['info']=info
f.close()

读取文件内容:

import shelve
f=shelve.open('./copy_file/buwexia')
print(f.get('test'))
print(f.get('name'))
print(f.get('info'))

输出:

(1, 2, 3, 4)
['haha', 'enen', 'yoyo']
{'age': 24, 'sex': 'm'}

xml模块

xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单

# Author:haha

import xml.etree.ElementTree as ET

tree=ET.parse('xml_file')
root=tree.getroot()
print(root.tag)
#输出:data

#遍历整个xml文档
for child in root:
    print(child.tag,child.attrib)
    for i in child:
        print(i.tag,i.attrib,i.text)
#输出:
'''
country {'name': 'Liechtenstein'}
rank {'updated': 'yes'} 2
year {} 2008
gdppc {} 141100
neighbor {'name': 'Austria', 'direction': 'E'} None
neighbor {'name': 'Switzerland', 'direction': 'W'} None
country {'name': 'Singapore'}
rank {'updated': 'yes'} 5
year {} 2011
gdppc {} 59900
neighbor {'name': 'Malaysia', 'direction': 'N'} None
country {'name': 'Panama'}
rank {'updated': 'yes'} 69
year {} 2011
gdppc {} 13600
neighbor {'name': 'Costa Rica', 'direction': 'W'} None
neighbor {'name': 'Colombia', 'direction': 'E'} None
'''
for child in root.iter('year'):#指定一个key值,查看text值
    print(child.tag,child.text)
#输出:
# year 2008
# year 2011
# year 2011

#修改和删除xml文档内容
for child in root.iter('year'):
    new_year=int(child.text)+2
    child.text=str(new_year)
    child.set('update','yes')
tree.write('xml_file')

for child in root.iter('year'):
    print(child.tag,child.text)
#输出:
# year 2010
# year 2013
# year 2013

for country in root.findall('country'):
    rank=int(country.find('rank').text)
    if rank>5:
        root.remove(country)

tree.write('xml_file')

自己创建xml文档:

import xml.etree.ElementTree as ET

new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={"checked": "no"})
sex = ET.SubElement(name, "sex")
name.text='haha'
age.text = '33'
name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
age = ET.SubElement(name2, "age")
age.text = '19'
name2.text='enen'
et = ET.ElementTree(new_xml)  # 生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True)

ET.dump(new_xml)  # 打印生成的格式

configparser

生成config配置文件

import configparser

config=configparser.ConfigParser()
config['DEFAULT']={'ServerAliveInterval':'45',
                   'Compression': 'yes',
                    'CompressionLevel': '9'}

config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
config['topsecret.server.com']['Host Port'] = '50022'     # mutates the parser
config['topsecret.server.com']['ForwardX11'] = 'no'  # same here
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini','w') as configfile:
    config.write(configfile)

读取配置文件

import configparser

config=configparser.ConfigParser()
config.read('example.ini')
print(config.sections())#打印除default外的其他节点
print(config['bitbucket.org']['user'])#打印指定节点下的数据
print(config.defaults())#打印default下面的配置数据
print('bitbucket.org' in config)#判断指定数据是否在config中
print(config.options('bitbucket.org'))#打印指定节点的子列表+default下的key值数据
#输出:['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
print(config.items('bitbucket.org'))#打印指定节点+default下的数据
#输出:[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
print(config.get('bitbucket.org','user'))#打印指定节点下指定key值的value数据
#输出:hg
print(config.getint('topsecret.server.com','host port'))#打印指定节点下指定key值的value int数据
#输出:50022

修改

config.set('bitbucket.org','user','haha')#修改指定节点的指定key值的value值,没有就创建
print(config.has_option('bitbucket.org','user'))#判断指定节点是否包含指定key值
print(config.add_section('bitbucket.org'))#添加指定节点
print(config.has_section('bitbucket.org'))#判断有无指定节点,没有就创建
config.remove_section('bitbucket.org')#删除指定节点
config.remove_option('bitbucket.org','user')#删除指定节点的指定key栏数据
config.write(open('example.ini','w'))#覆盖原来的文件

hashlib模块

用于加密相关的操作
md5加密:

import hashlib

md=hashlib.md5()
md.update(b'hello')
print(md.hexdigest())
md.update("It's me,哈哈".encode(encoding='utf-8'))
print(md.hexdigest())

#验证
md2=hashlib.md5()
md2.update("helloIt's me,哈哈".encode(encoding='utf-8'))
print(md2.hexdigest())
#输出:
'''
5d41402abc4b2a76b9719d911017c592
12c18ee8a7b5bfa3ccb0e98109f4b1ea
12c18ee8a7b5bfa3ccb0e98109f4b1ea
'''

其他加密模块类似,只是将md5改为相对应的加密方式,例:sha256

import hashlib

sh=hashlib.sha256()
sh.update(b'hello')
print(sh.hexdigest())
sh.update("It's me,哈哈".encode(encoding='utf-8'))
print(sh.hexdigest())

#验证
sh2=hashlib.sha256()
sh2.update("helloIt's me,哈哈".encode(encoding='utf-8'))
print(sh2.hexdigest())
#输出:
'''
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
69bb59a9dd5d6b843423ddcbdf050aae0c0023d858dfe66a9b3edf3253791ec6
69bb59a9dd5d6b843423ddcbdf050aae0c0023d858dfe66a9b3edf3253791ec6
'''

hmac加密
更加高端的加密手段

import hmac

h=hmac.new("hello',b'It's me,哈哈".encode(encoding='utf-8'))
print(h.hexdigest())
#输出:4c241f49f6acc0c8669d33a4ed805cd6

re模块

常用正则表达式符号

'.'     默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$'     匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
'+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?'     匹配前一个字符1次或0次
'{m}'   匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
 
 
'\A'    只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z'    匹配字符结尾,同$
'\d'    匹配数字0-9
'\D'    匹配非数字
'\w'    匹配[A-Za-z0-9]
'\W'    匹配非[A-Za-z0-9]
's'     匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
 
'(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
例:re.split('[0-9]','abc12f3GH'),结果为:['abc', '', 'f', 'GH']
re.sub      匹配字符并替换
例:re.sub('[0-9]+','|','abc12f3GH'),结果为:abc|f|GH
只替换一个数字:
re.sub('[0-9]+','|','abc12f3GH',count=1),结果为:abc|f3GH

注:

[] 单字符取一个,比如[abc]会匹配a或b或c
但是,如果[]里面加上^则会变成排除这个字符,如[^abc]就表示不是a、不是b、也不是c 
另外,在[]里面可以使用-表示一个范围,如[0-9]表示从0到9,类似的还有[a-zA-Z],如果要包含-字符,可以给它加上转义[\-]。 
关于[]常见的错误用法是:[ab|bc]用来表示ab或bc,实际上,它得到的结果是[abc|],即a或b或c或|这4个字符(单字符)的任意一个。这里可以改成(ab|bc)。 
总结:[]里面的特殊符有五个:[]-\^,其他字符都是普通字符,包括*.?等。 
说明: 
* ^在[^ 的首位时候才有特殊意义 
* [0-9 -在不是首尾的时候有特殊意义 
* \[ \] 因为占用[] 本身字符,所以有特殊意义 
* \本身是转义符,有特殊意义

反斜杠的困扰:

print(re.search(r'\\','abc\d'))
#输出:<re.Match object; span=(3, 4), match='\\'>

flags匹配模式:

re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
例:re.search('[a-z]+','abcAMK',flags=re.I)
输出:<re.Match object; span=(0, 6), match='abcAMK'>
M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
例:re.search('^[0-9]+','abcb\n123',flags=re.M)
输出:<re.Match object; span=(5, 8), match='123'>
S(DOTALL): 点任意匹配模式,改变'.'的行为
例:re.search('.+','abcb\n123',flags=re.S)
输出:<re.Match object; span=(0, 8), match='abcb\n123'>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容