2020-08-09 实操项目(收发邮件)

【明确项目目标】

学员小贾是一名外贸人员,每到了节假日,要给客户发祝福邮件。

虽然现在群发邮件比较方便,但还是要每次手动添加收件人的邮箱。小贾想:要是能够自动发送邮件给这些人就好了。

除了要学习这个模块相关的知识之外,我认为更重要的仍是掌握【学习模块的方式】,也可以理解为掌握【学习新知识的方式】。

这也是我们的另一个项目目标:学会自学新模块

【分析过程,拆解项目】

版本1.0,主要是根据需求,自己寻找和学习相关的模块,然后给自己发一封最简单的邮件。

版本2.0呢,还是给自己发邮件,但邮件应该更完整,包括邮件头(就是发件人、邮件标题等),和正文内容。

版本3.0呢,主要是从单一收件人,变成多收件人,也就是群发一封完整的邮件。

【逐步执行,代码实现】

【版本1.0:学习模块,发一封简单邮件】

在编程世界中,我们不需要什么知识都一把抓,而是遇到问题之后,产生了某种需求,才会去找对应的解决方案

这个方案可能是某个模块,也可能是某个函数~

就像在第一个PK小游戏项目中,我们想:要是能够随机生成某个区间内的数字,替代固定的血量值,可能会好一点。于是我们就学习并引入了random模块

其实,只要搜索关键词“发送邮件 python”,就能找到解决方案。


搜索后你看到这样的页面,不用逐一点进去看就能知道:1.Python可以解决这个问题;2.方法是smtplibemail这两个模块。

而且还会知道:smtplib是用来发送邮件用的,email是用来构建邮件内容的。这两个都是Python内置模块

为了方便自己理解,我们可以尝试把它画下来:

负责发送邮件的smtplib模块,和负责构造邮件内容的email模块,就是我们今天要学习的新模块~

一般,提供的关键字越多,搜索引擎返回的结果越精确。我们可以使用+号或者空格连接关键词,也可使用之前学习的andor来连接,其含义和之前学习的一样,分别表示“并且”和“或者”。

找到解决方案并大致了解模块之后,重头戏来了——学习这两个模块

昨天我们已经提供了一些学习的渠道,我们以smtplib模块为例来实操一下:

对于smtplib模块,我们想要去查看它的官方文档,也只需要在浏览器里搜索关键词“smtplib python”就好。

你能看到,第1个搜索结果是Python 3.7.2版本的smtplib模块介绍。打开这个网址,你看到满屏的英文:

如果你英文够好,那就可以去阅读;如果你英文不太好,也可以使用谷歌浏览器自带的“谷歌翻译”功能,将页面翻译成中文再阅读。

这个文档提供的内容有:需要向smtplib模块输入什么;smtplib模块能做什么;smtplib模块返回的是什么;常见的报错;SMTP对象有哪些方法及如何使用;一个应用实例

如果是这么讲,你会发现逻辑还是蛮清晰的。但它依然对新手蛮不友好,读起来比较痛苦。

如果你能够接受这种难度的文档,那么照着这个去写代码是最好不过的,毕竟它是官方文档。但如果你不能接受呢,还有一些方案。

关键词换成 “smtplib 教程” ,你就能看到好多好多中国人编写的内容。在可读性上,是要比官方文档好一些的,但缺点在于良莠不齐。你可以自行挑选适合自己的去阅读。

上一关我们总结了模块三问函数;属性或方法;格式。今天学习的两个模块比较简单,我们就不一一回答了,我们直接带着两个问题去学。

关于第1个问题,需要你现在点开搜索到的内容看看,你可以看别人的简介;也可以直接看代码,多对比不同人写的代码,那些重复出现的代码可能就是我们要找的方法。

总结一下这些内容,如果我们要发送邮件,就需要用到smtplib模块的以下方法:

第三行,server是一个变量,smtplib.SMTP()是变量server的值。我们已经知道了smtplib是模块的名称,那SMTP是什么意思呢?

请你先在自己电脑的VS Code上新建一个.py文件。注意:这个.py文件不能命名为email.py,而且你存放这个py文件的文件夹里,也不能有email.py同名文件。这是由于我们后面要调用email模块,如果将文件也命名为email,会造成报错。

现在请你把上面的代码复制进去。按住Ctrl键并点击SMTP ,会看到对SMTP的解释:

可以看到,SMTP 是一个类(class),再往下面滑可以看到其中包含了很多函数,第二到第五行的函数就是 SMTP 类下的方法。

要想调用 smtplib 模块下、SMTP 类下的方法,应该这样写:smtplib.SMTP.方法

我们看到的那段代码,则是为了减少代码冗余,已经将需要重复出现smtplib.SMTP赋值给了变量,可见,在编程的世界有多讨厌重复了。所以还是采用这种写法吧。

这样我们就能够调用需要的函数了,那这些函数有什么含义,要怎么用呢?继续探索。

其实我们只要知道SMTP是什么就能够明白代码的含义了,现在赶紧去搜索一下 “SMTP” 吧。

对,SMTP (Simple Mail Transfer Protocol)翻译过来是“简单邮件传输协议”的意思,SMTP 协议是由源服务器到目的地服务器传送邮件的一组规则。

可以简单理解为:我们需要通过SMTP指定一个服务器,这样才能把邮件送到另一个服务器。

第四行代码,就是干这个工作的,连接(connect)指定的服务器

host是指定连接的邮箱服务器,你可以指定服务器的域名。通过搜索“xx邮箱服务器地址”,就可以找到。

port 是“端口”的意思。端口属于计算机网络知识里的内容,你可以自行搜索了解,现在我们只要知道它是一个【整数】即可。

我们需要指定SMTP服务使用的端口号,一般情况下SMTP默认端口号为25

如果25行不通,你可以通过搜索或者去邮箱设置里面查看端口。比如,如果我打算用自己的企业邮箱来发邮件,登录邮箱后,在【设置-选项-POP和IMAP】里面可以看到这些信息:

包括服务器名称,端口和加密方式。服务器名称是mail.forchange.tech,端口是587。你可以登录自己的邮箱,查看这些信息,接下来跟着我一起写代码。

现在参数确定了,代码写出来应该长这样:

接下来的实操,以QQ邮箱为例来展示操作。我们可以搜索“QQ邮箱 smtp设置”得到hostport这两个参数。

两个参数都有了。SMTP服务器地址是:smtp.qq.com,端口是465587,那就让我们去写代码吧!

这里有两种写法,一是使用默认端口:25

二是,尝试搜索到的端口,比如465。这时会有些不同,QQ 邮箱采用的加密方式是SSL,我们需要写成这样:

后面,我们采用的是第二种写法。(大家可以先尝试第一种默认端口,如果不行则需要查找服务器对应的端口。)

提醒!QQ 邮箱一般默认关闭SMTP服务,我们得先去开启它。请打开https://mail.qq.com/,登录你的邮箱。然后点击位于顶部的【设置】按钮,选择【账户设置】,然后下拉到这个位置。

就像上面的一样,把第一项服务打开。需要用密保手机发送短信,完成之后,QQ 邮箱会提供给你一个授权码,授权码的意思是,你可以不用QQ的网页邮箱或者邮箱客户端来登录,而是用邮箱账号+授权码获取邮箱服务器的内容。

如果你打算用QQ邮箱自动发邮件,请保存好这个授权码。在你使用SMTP服务登录邮箱时,要输入这个授权码作为密码登录,而【不是】你的邮箱登录密码

若在设置和开启SMTP服务的过程中有遇到不可逾越的障碍……比如记不清密保手机,那么欢迎你……换个邮箱试试看。只是要重新查找服务器地址,端口和加密方式。这个过程中,保持耐心~

理解了SMTP的含义,下面几行代码的作用也就好理解了:

第五行代码,login是登录的意思,也就是登录你指定的服务器用的,需要输入两个参数:登录邮箱授权码

把两个参数放在最前面。这部分的代码我们也可以写出来了:

一个提醒:由于用户名和授权码属于敏感信息,所以我们在本关不会提供用于输入账号和密码的练习区。也就是说,下面的步骤都需要你在自己的电脑上运行。如果还没有新建py文件的,就现在动动手吧。

另外,为了运行代码的方便,我们暂时就大大咧咧地将授权码放在代码里,不过为了安全起见,更好的做法还是利用input()函数来输入,而不是直接展示哟。

第六行代码sendmail是“发送邮件”的意思,是发送邮件用的,sendmail()方法需要三个参数:发件人,收件人和邮件内容

这里的发件人from_addr与上面的username是一样的,都是你的登录邮箱,所以只用设置一次。

msg.as_string()是一个字符串类型:as_string()是将发送的信息msg变为字符串类型。

这样写还不完整,因为电脑不知道你要发送的信息msg是什么,我们也没有定义。这就需要用到email 模块,后面会解决的。

最后一行代码,quit是“退出”的意思,就是退出服务器。

现在,我们就学习完smtplib模块的方法了,也能够知道这个模块的具体功能,也就是这些方法怎么用。

现在我们可以把上面写好的代码放在一起,以QQ邮箱为例:

现在我们已经搞定了一半,接下来我们就会开始构建邮件的正文内容,让这个程序能跑起来。

我们就要用到构建邮件内容的email 模块。学习email 模块的过程我就不再展示了,请你自己动手。在这之前,有必要先回顾一下之前学习的渠道,以及学习的方式:带着目的学习

那我们就直接进行实操阶段啦。email 模块:也就是用来写邮件内容的模块。这个内容可以是纯文本、HTML内容、图片、附件等多种形式

每种形式对应的导入方式是这样的:

from … import …语句上一关我们已经学习过了。与直接导入整个 smtplib 模块(import smtplib)不同,这里我们只是从模块中导入一个或几个函数的做法。

同样,你可以复制上面的内容到本地的编辑器上,按住 ctrl 点击查看含义

请你按住ctrl同时点击mime,你会看到一个名为init.py空文件,这说明 email是其实是一个“包”

这就要谈到“模块”和“包”的区别了,模块(module)一般是一个文件,而包(package)是一个目录,一个包中可以包含很多个模块,可以说包是“模块打包”组成的

但为什么看到那个空文件,就能知道email是包呢?这是因为Python中的包都必须默认包含一个init.py的文件

init.py控制着包的导入行为。假如这个文件为空,那么我们仅仅导入包的话,就什么都做不了。所以直接import email是行不通的。

所以,我们就需要使用from … import …语句,从email包目录下的【某个文件】引入【需要的对象】。比如从email包下的text文件中引入MIMEText方法。中文说起来有点复杂,看代码就懂了:

下面,我们先从【构建纯文本的邮件内容】开始,也就是我们版本1.0的功能:发一封最简单的一句话文本邮件。

通过简单的学习,我们就能发现MIMEText()方法需要输入三个参数:文本内容,文本类型和文本编码

文本内容,我就写一句最简单的“send by python”吧。

好,现在终于可以把用email构建的正文内容,用smtplib模块发送啦。

我又要提醒你,在开始码这段代码之前,最好再梳理梳理代码结构。这是我建议的结构:

也就是这样:

我们在看别人代码的时候,也可以寻找结构清晰的代码作为参考,这样我们找到有用知识的概率也会提高。

按照这个结构,代码就能够码出来了。这是我的版本,你可以同样在自己的编辑器上写一写。记得准备好 QQ 邮箱和授权码(如果不是QQ邮箱,记得替换端口port参数),收件邮箱就写你自己的邮箱:

你收到邮件了吗?

如果发生报错的话,也没关系。这里我收集了几种典型报错信息:

ValueError: server_hostname cannot be an empty string or start with a leading dot.

看到报错,不要慌,小场面。在学习 Python 的过程当中,我们难免会遇到这种报错,这并非坏事,有报错才有成长。当出现报错的时候,我们去阅读报错,读不懂就去搜索

直接在网络搜索这个报错信息,我们会得到结论:如果你的Python版本是3.7,很可能发生这种报错。因为Python 3.7修改了ssl.py,导致smtplib.SMTP_SSL也连带产生了问题。

而解决方法也很简单:

加入host参数(邮箱服务器地址后),这个问题应该就迎刃而解了。

如果你用的是QQ以外的其他邮箱,也可能会出现一种报错。比如利用我的企业邮箱的话,就会出现如下报错信息:

smtplib.SMTPException: No suitable authentication method found

搜索后,我们很快就会发现,解决方案是:在登录(login)之前调用starttls()方法就可以了。也就是在代码中加入这样一行:

这些问题基本上都能通过搜索解决。如果你搞不清楚是什么问题的话,试一试将端口参数改一下,使用默认端口25

经过一番缠斗,现在你应该可以去查收你用 Python 发出的第一封邮件了!

在收件箱,你看到的内容大概是这样的:

但是,现在还不能算是一封完整的邮件,没有发件人信息,没有主题,正文内容太简单......这就是我们接下来要干的事情:

【版本2.0:给自己发一封完整邮件】

我们先来丰富邮件头:

邮件头(header,没错它也叫header)是这一块区域,包括主题、发件人、收件人等信息:

现在你可以直接去搜索别人的代码看看,请打开浏览器搜索“发邮件 python”并浏览查看其他人的代码,看和我们之前写好的代码存在哪些区别。

区别就在于,别人的代码多了这几行:

第一行代码,从email包引入Header()方法Header()是用来构建邮件头的。

标准邮件需要三个头部信息:From , To 和 Subject ,第三到五行代码就提供了这三个信息。

这里我们可以自定义,比如from发件人邮箱地址,to收件人邮箱地址,主题“python test”。

现在收到邮件就有点不一样了:

除了可以直接用邮箱地址之外,你还可以自定义内容,比如:

接下来,我们要想想怎么丰富邮件内容了。

原本邮件内容是写在这里:

如果你想要写很长的内容,建议先设置一个变量text用来放正文内容。

一般,邮件正文需要换行,不想一大串文字直接显示,我们可以在正文内容前后用''',还记得三引号的用法吧!

之前也提到了,出于保护隐私的目的,我们可以把收发件人,和授权码这些信息用input()变成需要输入的模式。

在版本3.0中,也将在一些地方用到这样的方式去改写代码,让整个程序更有“互动性”。

【版本3.0:群发完整邮件】

只要你搜索一下“Python 群发邮件”,就有海量的信息供你参考。我这里讲三种群发的方式:

一,是将收件人信箱的变量设置成一个可以装多个内容的列表

需要注意的是,to_addrs变量也将作为参数被传入Header方法中:

直接运行程序的话,这里就会发生错误:AttributeError: 'list' object has no attribute 'decode'

如果你有查看官方文档的好习惯,那么你会发现这是因为Header接受的第一个参数的数据类型必须要是字符串或者字节列表不能解码

也就是说,我们要将to_addrs变成一个字符串,怎么做呢?好像没有学过?其实,我们只需要对这行代码做一个这样的操作:

是否觉得眼熟?在关于文件读写的关卡中,有一个哈利波特的课堂小练习,其中我们简单地提到了join()函数,它的功能是把字符串合并

join()的用法是str.join(sequence),str代表在这些字符串之中你要用什么字符串来连接,你可以用逗号,空格,下划线等等。要将列表的元素合并,当然我们就直接使用逗号来连接了。

来打印一下转换前后的数据类型,验证一下。

这里有个小细节需要注意:我们将收件人变量名从to_addr改成了复数to_addrs之后,后面用到这个变量的地方,也要进行修改!

第一种方式,我们就讲到这里。

第二种方法是采用询问“是否继续输入邮箱地址”的方式,并用while循环来实现多个收件人的功能。

由于我们要存储输入的内容,供发邮件的时候使用。所以需要定义一个空列表to_addrs,用来存放收件人邮箱地址。输入邮箱地址的时候,地址会被追加写进列表。

因为循环次数不固定,所以我们选择while循环来做。我的这段代码是这样的,加了一个print()函数确认结果

除了收件人,我们把发件人和授权码也改成input模式。

接下来是最后一种方法:

用上一关学习的csv模块,将收件人邮箱写入csv文件,在发邮件时读取csv文件。

将邮箱地址写入csv模块的方法是write(),步骤是:1.引入csv模块;2.提供需要写入csv文件的数据,3.建文件并写入。

第一行,引入模块。第四行是等待写入csv文件的数据。

但是我们没有这样的文件,所以还需要新建一个to_addrs.csv文件。我们使用的是with语句新建文件,这样做的好处是:到达语句末尾时,会自动关闭文件,不需要close()

紧接着,我们定义了一个变量writer进行写入,将刚才的文件变量传进来。

之后就是进行数据写入,写入的方法是writerow()。通过遍历列表data将数据一行行写到了to_addrs.csv文件中。

读取的过程就异曲同工了。利用的是read()方法。步骤是:1.引入csv模块;2.打开csv文件;3.读取需要的数据。

row[1]表示csv文件中第1列的数据。想一想:wufeng和kaxi属于第0列的数据,邮箱地址则属于第1列的数据,所以第1列数据才是我们需要的!

接下来要做的就是把取出来的内容赋值给变量to_addrs,并在发送邮件时使用。先提个醒,注意哪些代码需要在for循环内部缩进

如果报错(报错是很正常的事情啦),记得排查我们之前说过的几个问题。

虽然读取稍微有点麻烦,但如果我们事先建了这样一个存储邮箱的csv文件,之后就可以一直复用它。从长期来看,还是利大于弊的。

而且在更高级的Python爬虫精进课程里面,我们也同样会用到csv模块,早点熟悉它会更好。

此外,你还可以为这个程序加一段异常处理代码,也就是try...except...语句来帮助你更好地处理你遇到的问题。

在这样与现实生活有关的项目中,往往会出现很多意想不到的障碍,比如能否顺利地拿到邮箱授权码,能否找到可用的端口,又比如偷懒把py文件直接命名为email.py而导致的报错等等

不过,正因为有太多人经历了这样的障碍,所以当你输入关键词搜索,就会发现这些都是前人走过的路,而他们的踊跃提问或分享,成为了让你走得更快的助推器。

到此,我们就学习完了新的模块,更重要的是,希望你掌握了学习的方法:懂得从需求出发寻找解决方案,也知道应该去哪里学习,并掌握了学习的方式。

希望你在码代码的过程中,逻辑结构越来越清晰,而且不那么害怕报错了,最后总能一步步克服困难。

掌握学习模块的方法的你,已经在事实上完成Python“入门”。你能在互联网上找寻很多有用的东西,帮助自己完成想做的项目。

或许你会产生疑问:用现成的邮件软件不好吗?用别人写好的代码不好吗?为什么一定要自己学习。

这个问题,可以从实用性前瞻性两个角度来回答。

从实用性上来说,单纯地懂得使用python发邮件并没有什么了不起。但它是一块砖,它能和别的砖组合在一起,构建成摩天大厦。最简单的例子,是我们之后可以利用:爬虫网络邮件的组合,做出更多有趣的事。

再者,即便是同块砖,反复地使用也能带来巨大的效率提升:如果要给一百人发送一百个内容不同的邮件,你就可以去写一个发邮件的程序,配合一些文件读写循环的操作,非常短时间地完成它。

前瞻性的角度来回答,就要讲个故事。

在上个世纪有一位年轻人,也写了类似这样一个发邮件的小程序,就像今天的你一样。

后来,他把这个功能做了好多升级:不能只发邮件啊,还得收邮件,存储邮件,日历提醒系统,订阅系统……最后,他把这些功能打包成一个电子邮件客户端

因为这个电子邮件客户端太好用,后来这个软件被一家更大的公司收购。这个年轻人,此时已经三十多岁,他也一并加入这家公司,负责这家公司的邮箱业务。

时过境迁,来到2010年,移动互联网时代刚刚拉开帷幕。做久邮箱业务的他,敏锐地感知到:在新的时代,人们使用的通讯方式也会迎来新的变革。而这种新的通讯方式,在许多地方和邮件都有着相通之处……

后来的故事,大家都知道了。他的名字叫做张小龙,他做出来的新产品,名字叫微信

上面提到的第二家公司是腾讯。他当时所负责的邮箱业务,就是我们这节课程里所使用的 QQ 邮箱

早期的 QQ 邮箱,运行笨重而缓慢。2006年底,张小龙率领团队用精简、轻便的思路设计新版本。2007年,新版的 QQ 邮箱上线,张小龙带领团队也开发了许多创新应用,将QQ邮箱打造为简洁易用、安全稳定的邮箱。2008年,QQ邮箱在腾讯公司获得“七星级产品奖”,张小龙的团队也获得腾讯的年度创新大奖,受到广大用户的欢迎。直至今天,它在中国依然是使用人数最多的邮箱产品。

上面提到的第一家公司是博大公司,张小龙卖出的产品是foxmail

而这一切,最开始都是从一行类似于'qqmail.sendmail()'的代码开始的。这和你今天所做的事情,并没有本质区别。再加一些存储功能、收邮件功能……借助一个图形界面的模块,你也能写出一个最原始版本的foxmail。

【课后练习】——自制动态二维码

练习目标:

我们会通过今天的作业,学习一个新的模块:MyQR,制作一个动态二维码。 

练习要求:

在昨天的练习里,你已经可以通过自己的学习,完成代码的升级。

所以,今天我们不妨多做些新的尝试。

这次的练习,没有提示,没有准备好的网址。

需求很明确:请你在本地编辑器(如vscode、Pycharm),用 Python 制作一个动态二维码。

所以,请你运用在课堂上看到的提示和知识,去思考,去搜索,去学习,完成今天的练习。

【了解新模块】

请去了解一下,要用什么模块来完成这个需求

不用担心,这个模块并不难。

这一个步骤你可以给自己制定一个目标:

读懂一个用 Python 制作动态二维码的代码

【代码实操】

你应该已经知道了这个模块是:MyQR,也能读懂相关的代码。

请你自学相关模块知识后,自行下载一个gif,然后在本地编辑器(如vscode、Pycharm)完成代码吧。

对了,不要忘了先安装myqr模块,Windows终端里运行'pip install myqr',Mac终端运行'pip3 install myqr'

【参考代码】

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