flask-16day

Day1

flask依赖包

当执行pip install flask后,会发现多了这些依赖
1.Flask flask核心库
2.Jinja2 模板渲染库
3.Markupsafe 安全标签库 只要flask返回模板或者标签时,都会依赖它
4.Werkzeug 德文“工具”的意思,应用程序网关接口库 WSGI,flask项目启动基于Werkzeug

启动项目实现hello world

注意:尽量不要使用pycharm中自带的flask模板创建flask

启动服务:

from flask import Flask # 导入flask核心类,创建Flask应用对象
app = Flask(__name__) # app-application,实例化的flask对象
app.run() # 启动Flask

实现helloworld

from flask import Flask 
app = Flask(__name__) 
@app.route("/index"):   # 为flask应用对象增加路由
 def index(): # 与路由绑定的视图函数
     return "hello world" # 返回,相当于响应

if __name__ == '__main__':
      app.run()

response

1.return "hello world"

2.return render_template("xxx.html")
html文件的默认存放路径是/templates

3.return redirect("/home")

重定向路由

@app.route("/home")
def home():
    return "home主页"


@app.route("/red")
def red():
    return redirect("/home")

当访问/red时,http status 302,3xx表示当前浏览器要做出指令。
请求时,response header中有参数location:http://127.0.0.1:5000/home,就会根据location对应的地址跳转。

小知识:pycharm中redirect("/home")("/home")会有小黄块,提示的意思是,不知道这个/home存在或者不存在,所以可以把templates标记为templates folder,这样黄色的小块就不在了。

image.png

4.return send_file("文件路径")
打开,并返回文件内容,并自动识别文件类型,在response header中加入,不能识别的类型,仅会做下载处理。(其实所有的都会下载,只是浏览器能够识别图片、map4,所以给你播放出来了。并且把Content-Type作为标签放到了页面上,识别文件类型的能力取决于浏览器,如wma文件,微软自带的录音文件格式,所以只有ie浏览器能识别,而其他浏览器不能识别)
如:
放一个jpg文件,response header中Content-Type: image/jpeg
放一个mp4文件,response header中Content-Type: video/mp4
Content-Type :文件类型

二进制文件的第一行,会写文件类型,如果没有写文件类型,就是普通的文本文件。

5.jsonify 返回标准格式

@app.route("/get_json")
def get_json():
    data = {"username": "tony"}
    return jsonify(data)

Content-Type: application/json

flask1.1.1以上版本,可以直接使用 return data,即return一个字典时,就是在执行jsonify,不建议使用,因为要兼容低版本。

修改app.config['JSONIFY_MINETYPE'],就是修改jsonify解析时返回的response header中Content-Type

request

1.请求方式

@app.route("login",method=["GET","POST"]) #在路由后面添加路由支持的请求方式

2.获取请求参数

@app.route("/login", methods=["GET", "POST"])
def login():
    print(request.form) 
    print(request.url)
    print(request.url_charset)
    print(request.url_root)
    print(request.url_rule)
    print(request.values)
    print(request.values.to_dict())
    print(request.args.to_dict())
    data = {"username": "tony"}
    return jsonify(data)

request.form ,获取formdata中的数据
to_dict(),如果类型是ImmutableMultiDict,都可以用to_dict()
request.url,获取请求的完整url
request.url_charset,获取请求url的编码方式
request.url_root,获取请求url的ip和port
request.url_rule,获取请求路由
request.values,获取post、get请求的请求数据,包括url和formdata中的数据
request.args,获取请求参数,类型是ImmutableMultiDict,支持to_dict(),get(key)

3.上传文件、保存文件

html文件部分

<body>
<form action="http://127.0.0.1:5000/upload" method="post" enctype="multipart/form-data">
    上传文件:<input type="file" name="my_file">
    <button type="submit">提交</button><br>
</form>

后端:

@app.route("/upload", methods=["POST"])
def upload():
    print(request.files)  # FileStorage对象是Flask的文件特殊对象
    # 打印结果:ImmutableMultiDict([('my_file', < FileStorage: '' ('application/octet-stream') >)])
    my_file = request.files.get("my_file")  # 获取FileStorage文件对象
    my_file.save(my_file.filename)  # 保存文件
    return "200 ok"

4.其他数据
request.headers
request.cookies
request.path==request.url_rule
request.host
request.host_url

5.特殊的提交方式获取
content-type:application/json
这时,request.form、request.arg是没有数据,放在request.json中
request.json:获取content-type:application/json 时提交的数据

content-type无法被识别时,放在request.data中
request.data:获取content-type无法被识别或不包括有form字眼,原始请求中的数据 b''

6.登录示例:
前端:

<body>
<form action="http://127.0.0.1:5000/login" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="pwd"><br>
    <button type="submit">提交</button><br>
</form>

flask

@app.route("/index")
def index():
    return "欢迎进入首页"


@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return render_template("login.html")
    if request.method == "POST":
        if request.form.get("username") == "ltx" and request.form.get("pwd") == "123":
            return redirect("/index")
        else:
            return "error,用户名或密码错误"

Flask session

Session 服务器端键值对
Cookie 客户端的键值对

flask的session交由客户端保管机制:
1.开启session[username]=123
{
username:123
}
2.序列化字典==字符串
3.加密字符串SecretKey 密钥字符串

接收反序列化session
1.从cookie中获取到一个叫session key的值
eyJ1c2VyIjoibHR4In0.Y2vCsg.VQloai4PfMQHN_gOp_bLUvdaEkQ
2.通过SecretKey 解密session
3.反序列化成字典

@app.route("/index")
def index():
    if session.get("user")=="ltx": #判断session的用户名是否正确
        print(session.get("user"))
        return "欢迎进入首页"
    else:
        return redirect("/login")


@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return render_template("login.html")
    if request.method == "POST":
        if request.form.get("username") == "ltx" and request.form.get("pwd") == "123":
            session["user"]=request.form.get("username") #新增session
            return redirect("/index")
        else:
            return "error,用户名或密码错误"

Jinja2

{{}} 引用变量参数
{%%} 逻辑代码

jinja2的简单实用:变量、循环、if判断

# 模拟数据库
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}

STUDENT_LIST = [
    {'name': 'Old', 'age': 38, 'gender': '中'},
    {'name': 'Tony', 'age': 31, 'gender': '男'},
    {'name': 'EDU', 'age': 39, 'gender': '女'}
]

STUDENT_DICT = {
    1: {'name': 'Old', 'age': 38, 'gender': '中'},
    2: {'name': 'Tony', 'age': 31, 'gender': '男'},
    3: {'name': 'EDU', 'age': 39, 'gender': '女'}
}

stuinfo.html

<body>
    {{stu_info}}

    <table border="1">
        <tr>
            <td>name</td>
            <td>age</td>
            <td>gender</td>
        </tr>
        <tr>
            <td>{{stu_info.name}}</td>
            <td>{{stu_info.get("age")}}</td>
            <td>{{stu_info["gender"]}}</td>
        </tr>
    </table>
    {{stu_list}}
    <table border="1">
        <tr>
            <td>name</td>
            <td>age</td>
            <td>gender</td>
        </tr>
        {% for stu in stu_list %} <!--for循环-->
        <tr>
            <td>{{stu.name}}</td>
            <td>{{stu.get("age")}}</td>
            <td> <!--if判断-->
                {% if stu["gender"]!='男' and stu["gender"]!='女'%}
                酷儿
                {% else %}
                    {{stu["gender"]}}
                {% endif %} <!--if结束-->
            </td>
        </tr>
        {% endfor %} <!--for循环结束-->
    </table>
    {{stu_dict}}
    <table border="1">
            <tr>
                <td>id</td>
                <td>name</td>
                <td>age</td>
                <td>gender</td>
            </tr>
        {% for foo,item in stu_dict.items() %}
        <tr>
            <td>{{foo}}</td>
            <td>{{item.name}}</td>
            <td>{{item.age}}</td>
            <td>{{item.gender}}</td>
        </tr>
        {% endfor %}
    </table>
</body>

flask

# 1.查看STUDENT放在studentinfo页面
@app.route("/stu")
def stu():
    return render_template("stuinfo.html", stu_info=STUDENT,stu_list=STUDENT_LIST,stu_dict=STUDENT_DICT)

可以自己创建一个标签,传入参数:


image.png

Day2

Flask路由参数

1.endpoint
不能重复,对应视图函数 ,endpoint默认是视图函数名。
请求时,通过路由找到endpoint,再通过endpoint找到对应的视图函数。

是否能反向操作,能通过endpoint找回路由吗?
通过url_for反向创建路由。

@app.route("/look_test", endpoint="/look")
def look():
    print(url_for("/look")) # 通过endpoint找到路由,所以结果是:/look_test
    return "999"

2.methods
支持的请求方式,列表形式:methods=["GET","POST"]

3.redirect_to
永久重定向,308,没有进入到视图层面直接跳转。

正常情况下:
请求-->路由匹配-->通过路由找到endpoint-->通过endpoint找到视图函数

redirect_to:
请求-->路由匹配时,发现有redirect_to,立即返回,不用再走后面的部分。

应用场景:当前地址不存在时,直接给你跳转到redirect_to的地址。api发生变更了,老用户没有新的访问地址,可以使用redirect_to。

4.strict_slashes
对url最后的/是否严格。
strict_slashes=True严格:url最后的有/不能访问,404
strict_slashes=False不严格:url最后的有/也可以访问

5.default
默认参数,如果有默认参数,视图函数中一定要接收参数,否则就会异常。

6.动态参数
<类型:变量>
类型:int string

@app.route("/look/<int:page>",methods=["GET"])
def look(page):
    print(page)
    return "这是第{}页".format(page)

访问:http://127.0.0.1:5000/look/10

@app.route("/look/<folder>/<filename>", methods=["GET"])
def look(folder, filename):
    filepath = os.path.join(folder, filename)
    return send_file(filepath)

传入不带类型的,不写默认为string

@app.route("/look/<folder>/<filename>", methods=["GET"])
def look(folder, filename):
    filepath = os.path.join(folder, filename)
    return send_file(filepath)

Flask 初始化(实例化)配置

app = Flask(__name__)从Flask跳转进去,init参数如下:


1.template_folder
template模板路径,默认为templates

app = Flask(__name__,template_folder="templates_new")

2.static_folder
静态文件路径,默认为static,static_folder的实现方式就是send_file。

在根目录下新建staticimage文件夹,分别方上1.jpg和2.jpg
访问:http://127.0.0.1:5000/image/2.jpg,报错404,
访问:http://127.0.0.1:5000/static/1.jpg,展示图片,跟send_file效果一样。
修改static_folder路径app = Flask(__name__,static_folder="image"),访问:http://127.0.0.1:5000/image/2.jpg,展示图片,而访问:http://127.0.0.1:5000/static/1.jpg报错404。

3.static_url_path
静态文件访问路径,默认值是static_folder

4.static_host
静态文件访问服务,比如:
<img src="/static/2.jpg" alt="">也能访问到图片,因为自动拼接出host。

Flask config配置

1.app.default_config 默认配置

default_config = ImmutableDict(
        {
            "ENV": None,
            "DEBUG": None,
            "TESTING": False,
            "PROPAGATE_EXCEPTIONS": None,
            "SECRET_KEY": None,
            "PERMANENT_SESSION_LIFETIME": timedelta(days=31),
            "USE_X_SENDFILE": False,
            "SERVER_NAME": None,
            "APPLICATION_ROOT": "/",
            "SESSION_COOKIE_NAME": "session",
            "SESSION_COOKIE_DOMAIN": None,
            "SESSION_COOKIE_PATH": None,
            "SESSION_COOKIE_HTTPONLY": True,
            "SESSION_COOKIE_SECURE": False,
            "SESSION_COOKIE_SAMESITE": None,
            "SESSION_REFRESH_EACH_REQUEST": True,
            "MAX_CONTENT_LENGTH": None,
            "SEND_FILE_MAX_AGE_DEFAULT": None,
            "TRAP_BAD_REQUEST_ERRORS": None,
            "TRAP_HTTP_EXCEPTIONS": False,
            "EXPLAIN_TEMPLATE_LOADING": False,
            "PREFERRED_URL_SCHEME": "http",
            "JSON_AS_ASCII": None,
            "JSON_SORT_KEYS": None,
            "JSONIFY_PRETTYPRINT_REGULAR": None,
            "JSONIFY_MIMETYPE": None,
            "TEMPLATES_AUTO_RELOAD": None,
            "MAX_COOKIE_SIZE": 4093,
        }
    )

DEBUG 开启代码编辑时重启、Log打印级别最低、错误信息透传
TESTING 无限接近生产、不会开启代码编辑重启、Log打印级别较高、错误信息不透传
SECRET_KEY 设置secret_key,生成session,前面说过

app.config["SECRET_KEY"]="@@#!#!@"
app.secret_key="@@#!#!@"
# 效果都是一样的,但app.config["SECRET_KEY"]是直接改配置,效率更高

PERMANENT_SESSION_LIFETIME session的生命周期,默认是31天,如果修改值的话,单位是秒,默认值timedelta(days=31)代表31天对应的秒。app.config["PERMANENT_SESSION_LIFETIME"]=3600*24

SESSION_COOKIE_NAME 存放在浏览器cookie中session名,第一个字符不能是空格

JSONIFY_MIMETYPE jsonify的标准格式,前面有说过

2.Flask 快速配置
使用app.config.from_object()快速切换不同环境配置

在settting.py存放各项配置

class DebugConfig: # 开发环境
    DEBUG = True
    SECRET_KEY = "123!@#$%%^"


class TestingConfig: # 测试环境
    DEBUG = False
    SECRET_KEY = "正式环境需要一个很复杂的SECRET_KEY"

导入 from setting import DebugConfig,TestingConfig,使用app.config.from_object(TestingConfig)或app.config.from_object(DebugConfig)就能快速切换不同环境的配置

from flask import Flask
from setting import DebugConfig,TestingConfig
app = Flask(__name__)
app.config.from_object(TestingConfig)


@app.route("/index")
def index():
    return "欢迎你呀"

if __name__ == '__main__':
    app.run()

BluePrint 蓝图

蓝图的作用是 :功能隔离、路由隔离

1.蓝图示例一:

根目录下,有程序的入口:s2-bp.py,其他的模块app_01

s2-bp.py

from flask import Flask
app = Flask(__name__)

# 建立蓝图注册
from app_01.views import user
app.register_blueprint(user)

if __name__ == '__main__':
    app.run()

在app_01下views.py文件

from flask import Blueprint

# BluePrint 当作一个不能run的Flask实例

user = Blueprint("user", __name__)  # 参数:先是蓝图的名字


@user.route("/login")
def login():
    return "BP login"

此时访问:127.0.0.1:5000/login ,返回BP login

2.蓝图示例二

多个模块有同个路由,比如一个模块app_01是管理后台的登录接口,一个模块app_02有C端用户登录接口。使用url_prefixurl前缀参数解决。

s2-bp.py

from flask import Flask
app = Flask(__name__)

# 蓝图 建立蓝图注册
from app_01.views import user
from app_02.views import app_user
app.register_blueprint(user)
app.register_blueprint(app_user)

if __name__ == '__main__':
    app.run()

app_01下的views.py

from flask import Blueprint

user = Blueprint("user", __name__,url_prefix="/admin")  # 添加前缀


@user.route("/login")
def login():
    return "admin 管理端 BP login"

app_02下的views.py

from flask import Blueprint

app_user = Blueprint("app_user", __name__,url_prefix="/shop") 

@app_user.route("/login")
def login():
    return "shop商城 BP login"

在访问路由时,加上对应的前缀,如:
访问http://127.0.0.1:5000/shop/login,是访问app_02中的login
访问http://127.0.0.1:5000/admin/login是访问app_01中的login

Flask 特殊装饰器

@app.before_request
@app.after_request
@app.errorhandler(4xx or 5xx)

1.@app.before_request 请求进入视图函数之前
2.@app.after_request 请求结束,返回响应客户端之前

定义函数的顺序:be1--be2--be3--af1--af2--af3

正常 : be1--be2--be3--vf--af3--af2--af1

异常: be1--be2--阻断--af3--af2--af1

3.@app.errorhandler(4xx or 5xx) 自定义错误处理

@app.errorhandler(404)
def error404(ErrorMassage):
    print(ErrorMassage)
    return "页面{}不存在".format(request.path)

Flask endpoint补充

没懂 有机会再学

Day3

Flask 蓝图结构

1.回顾蓝图
前面翻翻吧

2.一个简单的蓝图结构
根目录下新建一个app01文件夹:
-static
-templates
-views
-models.py

根目录下新建一个manage.py文件

在app01下的__init__.py文件中:

from flask import Flask
from app01.views.user import user_bp

def create_app():
    app = Flask(__name__)
    # 配置
    app.config["DEBUG"]=True
    # 注册蓝图
    app.register_blueprint(user_bp)
    return app

views下的user.py

from flask import Blueprint

user_bp = Blueprint("user", __name__)


@user_bp.route("/login")
def login():
    return "登陆成功"

根目录下manage.py

from app01 import create_app
app=create_app()
if __name__ == '__main__':
    app.run()

__init__.py文件创建Flask实例、配置config、注册蓝图
在manage.py调用app.run()方法
views.py 注册路由、视图函数

使用python manage,py启动项目。

Flask CBV

flask中有两种视图,一种是基于函数的视图FBV,一种是基于类的视图CBV

flask视图函数注册路由的本质:
其实,route装饰器内部也是通过调用add_url_rule()方法实现的路由注册,只是route装饰器看起来更加美观。

from flask import Flask, views  # 导入CBV的视图基类

app = Flask(__name__)


class Login(views.MethodView):  # 继承CBV视图基类的最高类
    def get(self):  # get方法的视图函数实现
        return "GET OK 200"

    def post(self):
        return "POST OK 200"


# 为CBV添加路由
app.add_url_rule("/login", view_func=Login.as_view(name="login"))

if __name__ == '__main__':
    app.run()

as_view 把视图类转化为视图函数

Flask 监听端口 数据传递

app.run("127.0.0.1",5000)

IP对应本机访问IP,如果是0.0.0.0表示本机所有IP

端口对应应用程序

应用层:
浏览器-端口9528,对应用192.168.14.26:9527发起请求时,传递了b'' HTTP 1.1 / GET\t\n

网卡b'' HTTP 1.1 / GET\t\n 传递给操作系统
操作系统 解包 根据端口9527--传递给9527
WSGI:9527收到b'' HTTP 1.1 / GET\t\n ,Flask让WSGI把这些数据转换成对象environ
Flask收到WSGI转换的environ对象request_class(request类),转换为Flask的request样式,比如请求参数,转换为request.form

Flask-session

第三方组件

flask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存(交给客户端保管不安全),该组件则将支持session保存到多个地方,如:

  • redis
  • memcached
  • filesystem
  • mongodb
  • sqlalchmey

安装pip install Flask-session

def create_app():
    app = Flask(__name__)
    # 配置
    app.config["DEBUG"] = True
    # 在config配置之后,在注册蓝图之前,是三方组件的空间
    # 实例化一个session
    Session(app)

    # 注册蓝图
    app.register_blueprint(user_bp)
    return app

SESSION_SQLALCHEMY 数据库ORM

# session存储在redis
app.config["SESSION_TYPE"]='redis'
# 实例化
Session(app)

# 在login方法中设置session
class Login(views.MethodView):  # 继承CBV视图基类的最高类
    def get(self):  # get方法的视图函数实现
        session["username"]="电地大"
        return "GET OK 200"

Redis模块的简单用法

redis安装
https://redis.io/download/
启动服务

from redis import Redis

rdb=Redis()
rdb.set("username","NB")

print(rdb.get("username"))

存一个字典

rdb=Redis()
d={"key":"value"}
# 把dict转为byte
rdb.set("username",json.dumps(d))
# 把byte转为dict
print(json.loads(rdb.get("username")))

db参数:

rdb=Redis(host="127.0.0.1",port=6379,db=8) # db-->0-15,除了0,其他都会显示,数据隔离的作用

在redis服务中命令select 8

Flask-session高级源码阅读

看不懂 就这样吧。

app.config["SESSION_TYPE"] = 'redis'
app.config["SESSION_REDIS"] = Redis(host="192.168.14.25")  # 实例化,部署在内网的其他服务器
Session(app)

Day4

Flask请求上下文预备知识

1.线程安全
2.偏函数
3.OOP 面向对象

面向对象回顾

偏函数

简单的理解偏函数,它是对原始函数的二次封装,是将现有函数的部分参数预先绑定为指定值,从而得到一个新的函数,该函数就称为偏函数。相比原函数,偏函数具有较少的可变参数,从而降低了函数调用的难度。

from functools import partial

def abfun(a, b):
    print(a)
    print(b)
    return a + b


new_ab = partial(abfun, 2, 3)
print(new_ab)  # functools.partial(<function abfun at 0x000001BA7781D0D8>, 2, 3)
print(new_ab())  # 5

将原函数和原函数接收的参数一并存放,返回新函数,在执行新函数时,将参数传入原函数中一并执行。

from functools import partial

def abfun(a, b,x):
    print(a)
    print(b)
    return a + b+x
# 只知道一个参数的值
new_ab = partial(abfun,x=80)
print(new_ab)
print(new_ab(3,10))  # 93

线程安全

单线程读取19个,需要19s,打印内容为012345...19

import time

class Foo:
    pass

f = Foo()
f.num = 0


def add(i):
    f.num = i
    # 模拟IO操作需要1s
    time.sleep(1)
    print(f.num)


for i in range(20):
    add(i)

开启多线程,使任务在1.5s左右完成:
但打印的结果是19 19 19...19

import time
from threading import Thread

class Foo:
    pass


f = Foo()

f.num = 0


def add(i):
    f.num = i
    time.sleep(1)
    print(f.num)


for i in range(20):
    task=Thread(target=add,args=(i,))
    task.start()

使用深copy:

很快解决了阻塞 保证了公共对象的安全性
但浪费了大量的资源 拿空间浪费换取时间

import time
from threading import Thread,get_ident
from copy import deepcopy
class Foo:
    pass


f = Foo()

f.num = 0
local_dict={}

def add(i):
    # 深copy
    local_dict[get_ident()]=deepcopy(f)
    local_dict[get_ident()].num = i
    time.sleep(1)
    print("{}_{}".format(local_dict[get_ident()].num,get_ident()))
    # print(get_ident())

for i in range(20):
    task=Thread(target=add,args=(i,))
    task.start()


WSGI收取request

请求上下文:读flask源码
1.请求是如何到达flask应用的


由底层传到高层

请求上文

from werkzeug.wrappers import Request,Response
from werkzeug import run_simple
# run_simple监听操作系统传递来的数据
@Request.application
def app(req):
    print(req,req.method,type(req))
    return Response("200 ok")

run_simple("127.0.0.1",5000,app)

打印结果:

req # <Request 'http://127.0.0.1:5000/' [GET]> 
req.method # GET 
type(req) #<class 'werkzeug.wrappers.request.Request'>

falsk中的app.run()调用的就是run_simple()方法
一顿转换,转换为flask风格的request

image.png

environ是原始的请求信息,app

golbals.py中 --》请求上文


image.png

请求下文

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

推荐阅读更多精彩内容