Flask 从零开始

知识点一 (首先呢,先搭建一个git仓库,方便日后操作代码)

Git 全局设置:

git config --global user.name "Aries"
git config --global user.email "6148694@qq.com"

创建 git 仓库:

mkdir fisher
cd fisher
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/wanglei230/fisher.git
git push -u origin master

已有仓库?

cd existing_git_repo
git remote add origin https://gitee.com/wanglei230/fisher.git
git push -u origin master

总结:之前对Git仓库的创建,每次都是上网复制粘贴。这次学习,要多理解,争取每次自己能独立创建。

知识点二 pipenv (主要用于隔离环境)

vim编辑虚拟环境的位置

export PIPENV_VENV_IN_PROJECT=1   (bash_profile里填写此内容,可修改虚拟环境的地址为项目内)
vim ~/.bash_profile
source ~/.bash_profile

Python第三方类库下载pipenv

pip3 install pipenv   下载pipenv

指定虚拟环境的Python版本 (我这里是Python3.7.3,尽量下载3.6.0以上的,不然后续会有不兼容的报错)
pipenv --python 3.7.3

安装自定义Python版本的虚拟环境

进入虚拟环境

pipenv shell

退出虚拟环境

exit

查找虚拟环境的路径 (记得是中线- 不是下划线_)

pipenv --venv

/Users/Aries/fisher/.venv

删除虚拟环境

pipenv --rm
知识点三 pycharm里配置虚拟环境的解释器
Pycharm添加虚拟环境解释器
知识点四 管理虚拟环境的类库

pip freeze > requirements.txt

下载插件
pip install -r requirements.txt

参与项目 《鱼书》 http://yushu.talelin.com/

接下来所有的学习都会按照这个项目来进行

鱼书是公益性的项目 目的是:将自己不要的书,免费赠送他人

鱼书大致功能概况

  • 搜索书籍
  • 赠送书籍
  • 索要书籍
课前预习 做一个简单的api
from flask import Flask

app = Flask(__name__)


@app.route('/hello/')
def hello():
    return "第三遍来学习了,要加油"


app.run()
课前预习
提前准备的内容

需要提前下载好flask类库
pipenv shell 进入虚拟环境
pipenv install flask 下载第三方类库
pip list 可以查询已下载的类库列表

知识点五 Flask解决路由兼容 /hello /hello/

设定路由地址为 /hello

http://127.0.0.1:5000/hello 可以访问
http://127.0.0.1:5000/hello/ 访问找不到

访问不到hello/

如果兼容这两种输入
将路由设置为/hello/ 即可解决

路由兼容问题

知识点六 介绍两种路由的注册 Debug调试自动重启WEB服务器
  • 通过装饰器 @app.route('/hello') 优点:简洁方便
  • 通过 app.add_url_rule('/hello',view_func=hello) 优点:更加灵活
  • 增加debug参数,修改完代码,自动重启服务器
  • 装饰器 @app.route是通过调用add_url_rule而来的
from flask import Flask

app = Flask(__name__)

def hello():
    return "第三遍来学习了,要加油"

app.add_url_rule('/hello',view_func=hello)

app.run(debug=True)
知识点七 启动服务器添加host和端口号
app.run(host='0.0.0.0',debug=True,port=8080)
  • host 0.0.0.0 可以被外网访问 以及localhost 127.0.0.1 所有的网卡访问
  • port 是设置的端口号
知识点八 读取配置文件
  • config.py 新增文件 ####【变量名必须是大写字母】####
DEBUG = True
  • fisher.py
载入配置文件   app.config.from_object('config')
读取配置文件  print(app.config['DEBUG'])
读取配置文件
  • 疑问1 config配置文件里输入 debug=True 读取app.config['debug']的时候提示找不到‘debug’


    config
找不到‘debug’

答案:因为通过app.config.from_object读取的配置文件,会忽略掉小写字母,所以就找不到debug

  • 疑问2
    config里输入 debug =True 读取读取app.config['DEBUG']显示False


    False

    答案:因为Flask内置的DEBUG=False 所以即使不写也可以找得到
    如果你写了DEBUG=True 相当于把这个值覆盖了

知识点九 if name的作用
from flask import Flask

app = Flask(__name__)
app.config.from_object('config')
print(app.config['debug'])
@app.route('/hello')

def hello():
    return "第三遍来学习了,要加油"

#app.add_url_rule('/hello',view_func=hello)

if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=app.config['DEBUG'],port=8081)
  • 入口文件,只执行下面的内容
  • 如果此脚本被导入,不会执行下面的内容
知识点十 视图函数的return 和普通函数的return有何区别
@app.route('/hello')
def hello():
    return "<html>好好学习 </html>"

def hello1():
    return "<html>好好学习 </html>"
  • 视图函数的return不仅返回内容 还返回content-type


    视图函数return返回
知识点十一 response
from flask import Flask,make_response

@app.route('/hello')
def hello():
    header = {
        "content-type":"text/plain",
        }
    response = make_response("<html>开始读书了<html>",200)
    response.headers=header
    return response
知识点十二 return也可以按照response返回 更加便捷
@app.route('/hello')
def hello():
    header = {
        "content-type":"text/plain",
        }
    return "<html>DAYDAY UP</html>",200,header
return返回数据
自己练习 尝试写JSON格式的返回
@app.route('/hello')
def hello():
    header = {
        "content-type":"application/json",
        }
    result ={
        "status":200,
        "name":'wanglei',
        "desc":"leiziyaohaohaoxuexile "
    }
    return result,200,header
json格式的返回
总结
  • make_response 和 return 都可以返回数据
  • return 更便捷 make_response作为介绍,后续应该不会在出现了
项目 编写查询
  • 图书的查询 分为ISBN号查询和普通关键词查询

isbn编号13 13个0到9的数字组成

isbn编号10 10个0到9的数字组成,含有一些'-'

@app.route('/book/search/<q>/<page>')
def search(q,page):   //q为关键词  通过输入的q来判断是关键词还是ISBN
    is_key_isbn = 'key‘
    if len(q) == 13 and q.isdigit():   //isdigit是Python的内置函数来判断是否是纯数字
        is_key_isbn = 'isbn'
    if '-' in q and q.replace('-','').isdigit() and len(q)==10:
        is_key_isbn = 'isbn'
    else:
        is_key_isbn = 'key'
重构代码
  • 视图函数一定要简洁明了
  • 封装函数 复用性强
    创建helper.py
def is_isbn_or_key(q):
    is_key_isbn = 'key'
    if len(q) == 13 and q.isdigit():
        is_key_isbn = 'isbn'
    if '-' in q and q.replace('-','').isdigit() and len(q) == 10:
        is_key_isbn = 'isbn'

fisher.py去导入is_isbn_or_key

from helper import is_isbn_or_key

@app.route('/book/search/<q>/<page>')
def search(q,page):
    isbn_or_key = is_isbn_or_key(q)
请求api (判断完ISBN然后需要去请求接口)

创建http.py

import requests
class HTTP:

    def get(self,url,return_json=True):
        r =requests.get(url)
        # restful
        # json
        if r.status_code == 200:
            return r.json() if return_json else r.text //三元表达式 
        return {} if return_json else ''

首先呢 request url
再通过status_code去返回内容
status_code!=200 有可能是没有找到书籍 所以返回空
通过三元表达式 和if return 去简化表达式

知识点十三 三元表达式

r.json() if return_json else r.text
if 成立 执行 r.json 否则 r.text

知识点十四 静态方法 我也不太清楚

@staticmethod 来源于菜鸟课程

class A():

    def aa(self,a=1,b=3):
        return a+b

    @staticmethod
    def bb(a=5,b=10):
        return a+b
    @classmethod
    def cc(cls,c=11,d=20):
        return c+d
A = A()
print(A.aa())
print(A.bb())
print(A.cc())
/Users/Aries/fisher/.venv/bin/python /Users/Aries/fisher/test.py
4
15
31
Process finished with exit code 0
Traceback (most recent call last):
  File "/Users/Aries/fisher/test.py", line 21, in <module>
    print(A.aa())
TypeError: aa() missing 1 required positional argument: 'self'
  • 优点在于 @staticmethod 不需要self,cls这些参数
  • @staticmethod,@classmethod并且不用实例化 直接可以调用函数
知识点十五 python3里创建类后面的括号和不带括号区别

class Http(object):
class Http:

  • Python3中没有任何区别
  • Python2中一个代码经典类 一个代表新式类 知道就行 不需要了解太多
项目搜索功能 新增 yushu_book.py
from httper import HTTP
class YuShuBook:

    isbn_url = "http://t.talelin.com/v2/book/isbn/{}"
    keyword_url = "http://t.talelin.com/v2/book/search?q={}&count={}&start={}"

    @classmethod
    def search_by_isbn(cls,isbn):
        url = cls.isbn_url.format(isbn)
        result = HTTP.get(url)
        return result

    @classmethod
    def search_by_keyword(cls,keyword,count=15,start=0):
        url = cls.keyword_url.format(keyword,count,start)
        result = HTTP.get(url)
        return result
  • 完成isbn的搜索
  • 完成关键词的搜索
项目 搜索功能 视图函数去调用 yushu_book的search_by_keyword函数和search_by_isbn函数
@app.route('/book/search/<q>/<page>')
def search(q,page):
    isbn_or_key = is_isbn_or_key(q)
    if isbn_or_key == 'key':
        result = YuShuBook.search_by_keyword(q)
    else:
        result = YuShuBook.search_by_isbn(q)
    return result

请求接口 http://192.168.8.101:8081/book/search/9787501524044/1

返回结果:

{
    "author": [
        "蔡智恒"
    ],
    "binding": "平装",
    "category": "小说",
    "id": 1780,
    "image": "https://img3.doubanio.com/lpic/s1327750.jpg",
    "images": {
        "large": "https://img3.doubanio.com/lpic/s1327750.jpg"
    },
    "isbn": "9787501524044",
    "pages": "224",
    "price": "12.80",
    "pubdate": "1999-11-1",
    "publisher": "知识出版社",
    "subtitle": "",
    "summary": "你还没有试过,到大学路的麦当劳,点一杯大可乐,与两份薯条的约会方法吗?那你一定要读目前最抢手的这部网络小说——《第一次的亲密接触》。\\n由于这部小说在网络上一再被转载,使得痞子蔡的知名度像一股热浪在网络上延烧开来,达到无国界之境。作者的电子信箱,每天都收到热情的网友如雪片飞来的信件,痞子蔡与轻舞飞扬已成为网络史上最发烧的网络情人。",
    "title": "第一次的亲密接触",
    "translator": []
}
知识点十六 如何将字典转成字符串
import json

json.dumps(result)
知识点十七 flask的jsonfy
import flask import jsonfy
return jsonfy(result)
return json.dumps(result),200,"content-type:application/json"
  • 目前的话 直接返回result 就已经是JSON格式,
    可能是版本更新了,七月老师的版本还是只能显示字符串,
    字典无法显示数据 需要字典转换成字符串 才能显示
    目前版本不需要考虑 jsonfy 和 json.dumps(result) 作为一个知识点记录一下吧,有个印象
项目重构 提取Flask核心对象到app/init
  • 提取目的还是为了让启动页面干净
from flask import Flask

create_app():
  app = Flask(__name__)
  app.config.from_object('config')
  return app
知识点十八 蓝图
  • 蓝图不能独立存在,必须插入到app上


    蓝图
  • app/web/book.py

from flask import Blueprint

web = Blueprint("web",__name__)

@web.route('/book/search/<q>/<page>')
  • 蓝图在Flask核心对象上插入
def create_app():
    app =Flask(__name__)
    register_blueprint(app) //
    return app


def register_blueprint(app):
  form app.web.book import web
  app.register_blueprint(web)

知识点十九 拆分单蓝图
  • app/web/_init.py
from flask import Blueprint
web = Blueprint("web",__name__)
from app.web import book

知识点二十 flask 里的 request
@web.route('/book/search')
def search():
    //request.args['']可以获取到请求里?后面的内容
    q = request.args['q']
    page = request.args['page']
    isbn_or_key = is_isbn_or_key(q)
    if isbn_or_key == 'key':
        result = YuShuBook.search_by_keyword(q)
    else:
        result = YuShuBook.search_by_isbn(q)
    return result
request

知识点二十一 WTForms参数验证

  • pipenv install wtforms 首先虚拟环境先下载wtforms的模块

  • 新建一个forms的文件 在新建一个book.py


    forms
  • forms/book

from wtforms import Form,StringField,IntegerField
from wtforms.validators import Length,NumberRange

class SearchForm(Form):
    q = StringField(validators=[Length(min=1,max=30)])
    page = IntegerField(validators=[NumberRange(min=1,max=99)],default=1)
  • web/book
@web.route('/book/search')
def search():
    form = SearchForm(request.args)
    if form.validate():
        q = form.q.data.strip()
        page = form.page.data
        isbn_or_key = is_isbn_or_key(q)
        if isbn_or_key == 'key':
            result = YuShuBook.search_by_keyword(q)
        else:
            result = YuShuBook.search_by_isbn(q)
        return result
    else:
        #return {"msg":"输入内容格式有误!"}
        return form.errors   可以返回form里的自定义的报错信息
默认报错

这里的报错信息也可以自己设置 在form里

q = StringField(validators=[Length(min=1,max=30,message='关键词的字符应该是1---30位,请检查输入的关键词')])

自定义关键词参数
  • 设置输入空格的判断 DataRequired() 判断空格
    validators=[DataRequired(),Length(min=1,max=30)
    ![判断空格](https://upload-
    images.jianshu.io/upload_images/17753024-b0b1fc0e99071007.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
总结三点
  • form.errors 输入默认的报错信息
  • message 设置自定义的报错信息
  • DataRequired() 判断输入空格报错
知识点二十二 current_app
  • from flask import current_app
    current_app 相当于app
    这里不能在重新导入app了 会重复导入报错的 所以用current_app
    @staticmethod
    def formit_page(page):
        return (page-1)*current_app.config['PER_PAGE']
项目
  • 新增了secure.py 配置文件(存一些数据库密码等信息 安全级别高的)

  • 新增了setting.py 配置文件(存储普通信息)

  • 搜索关键词的代码 需要的 count start 通过page替换了一下

  • setting.py
    PER_PAGE=15

  • yushubook.py

from flask import current_app

    @classmethod
    def search_by_keyword(cls,keyword,page):
        url = cls.keyword_url.format(keyword,current_app.config['PER_PAGE'],cls.formit_page(page))
        result = HTTP.get(url)
        return result

    @staticmethod
    def formit_page(page):
        return (page-1)*current_app.config['PER_PAGE']
项目
  • 新建libs类 把httper.py help.py 把帮助类都放进去
  • 新建spider类 把yushu_book 放进来 放一些 持久化存储的数据


    优化代码结构
知识点二十三 sqlalchemy
  • 下载 flask_alchemy
  • 创建models文件


    models
  • String 字符串
  • Integer 数字类型
  • primary_key 主键
  • autoincrement 自增长
  • nullable 是否为空
  • unique 唯一 不重复 (ISBN)
  • default 默认值
实例化 SQLAlchemy

models.book.py

from sqlalchemy import Column,String,Integer

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()  实例化 SQLAlchemy

class Book(db.Model)://继承db.Model
  • 注册到app
from flask import Flask
from app.models.book import db  //关键代码
def create_app():
    app = Flask(__name__)
    app.config.from_object("app.setting")
    app.config.from_object("app.secure")
    register_blueprint(app)
    db.init_app(app)  //关键代码
    db.create_all(app=app)  //关键代码
    return app
``

###### 知识点二十四  链接数据库
secure.py  数据库信息存在这个配置文件里

from urllib import parse
pwd = "Gaojunqing1101111asdad@" //因为我的密码有特殊字符 需要转义
pwd_encode = parse.quote_plus(pwd)

数据库+驱动类型+账号+密码+服务器地址+端口号+数据库名
SQLALCHEMY_DATABASE_URI = f"mysql+cymysql://root:{pwd_encode}@39.107.60.13:3306/fisher"

``

  1. 因为栈顶没有内容了 所以报错了

2.解决方案1:

with app.app_context():
        db.create_all()

解决方案2:
db.create_all(app=app)
解决方案3:

cxt = app.app_context()
cxt.push()
db.create_all()
cxt.pop()
知识点二十五 Flask 上下文
image.png
from flask import Flask,current_app

app = Flask(__name__)

ctx  = app.app_context()
ctx.push()   推入应用程序栈中

a = current_app
b = current_app.config['DEBUG']
ctx.pop()   弹出栈
  • 首先呢,先检测appcontext栈顶是否为空 为空再去 requestcontext中 推入栈顶
  • 如果在请求中,appcontext不需要自己主动去推入,Flask会帮助它自动去推入到栈中
  • _request_ctx_stack 是对LocalStack栈的实例
  • push是推入
  • pop是弹出
  • 栈是 后进先出 队列是 先进先出
进程和线程的理解

进程相当于是一个车间
线程相当于是车间里的工人
一个车间可以有多个工人
一个进程里可以有多个线程

ViewModel
image.png
  • 鱼书API通过ISBN和关键词返回的内容比较乱

  • 通过viewModel合并成一个完整的数据结构

  • 新建一个 view_model 用于格式化数据


class  BookViewModel():

    #isbn搜索数据
    @classmethod
    def package_single(cls,data,keyword):
        returned = {
            'books':[],
            'total':0,
            'keyword':keyword
        }
        if data:
            returned['total'] = 1
            returned['books'] = [cls._cut_book_data(data)]
        return returned

    #关键词搜索数据
    @classmethod
    def package_collection(cls,data,keyword):
        rerurned = {
            'books':[],
            'total':0,
            'keyword':keyword
        }
        if data:
            rerurned['total'] = data['total']
            rerurned['books'] = [ cls._cut_book_data(book) for book  in data['books'] ]
        return rerurned

    @classmethod
    def _cut_book_data(cls,data):
        book = {
            'title':data['title'] or '',
            'publisher':data['publisher'] or '',  //原数据返回null 使用 or  来改写
            'pages':data['pages'] or '',
            'author':'、'.join(data['author']),  //原数据返回[] 使用join拼接
            'price':data['price'] or '',
            'summary':data['summary'] or '',
            'image':data['image'] or ''

        }
        return book
代码重构
  • 重构 yushu_book.py
from app.libs.httper import HTTP
from flask import current_app
class YuShuBook:

    isbn_url = "http://t.talelin.com/v2/book/isbn/{}"
    keyword_url = "http://t.talelin.com/v2/book/search?q={}&count={}&start={}"

    def __init__(self):
        self.total = 0
        self.books = []

    def search_by_isbn(self,isbn):
        url = self.isbn_url.format(isbn)
        result = HTTP.get(url)
        self.__fill_single(result)

    def search_by_keyword(self,keyword,page):

        url = self.keyword_url.format(keyword,current_app.config['PER_PAGE'],self.formit_page(page))
        result = HTTP.get(url)
        self.__fill_collection(result)

    def __fill_single(self,data):

        if data:
            self.total = 1
            self.books.append(data)

    def __fill_collection(self,data):

            self.total = data['total']
            self.books = data['books']

    def formit_page(self,page):

        return (page-1) * current_app.config['PER_PAGE']
  • 重构view_models/book.py
class BookViewModel:

    def __init__(self,book):
        self.title = book['title'] or ''
        self.publisher = book['publisher'] or ''
        self.author = '、'.join(book['author']) or ''
        self.image = book['image'] or ''
        self.price = book['price'] or ''
        self.summary = book['summary'] or ''
        self.pages = book['pages'] or ''

class BookCollection:
    def __init__(self):
        self.total = 0
        self.books = []
        self.keyword = ''

    def fill(self,yushu_book,keyword):
        self.total = yushu_book.total
        self.keyword = keyword
        self.books = [BookViewModel(book) for book in yushu_book.books]
  • web/book
import json

from app.view_models.book import BookViewModel, BookCollection
from app.libs.helper import is_isbn_or_key
from app.spider.yushu_book import YuShuBook
from flask import request
from . import web
from app.forms.book import SearchForm
@web.route('/book/search')
def search():
    form = SearchForm(request.args)
    books = BookCollection()

    if form.validate():
        q = form.q.data.strip()
        page = form.page.data
        isbn_or_key = is_isbn_or_key(q)
        yushu_book = YuShuBook()

        if isbn_or_key == 'isbn':
            yushu_book.search_by_isbn(q)
        else:
            yushu_book.search_by_keyword(q,page)

        books.fill(yushu_book,q)
        return json.dumps(books,default=lambda o:o.__dict__)
  //books 这里是一个对象  没法返回值  所以通过__dict__去返回
    else:
        #return {"msg":"输入内容格式有误!"}
        return form.errors
  • 序列化对象


    序列化
  • 把对象 序列化成字典 dict
    default=lambda o:o.dict
项目 访问静态文件 创建一个static的文件夹 存放图片
Jinja2 if 语句
<body>
  {#<p>{{data.name}}</p>
    <p>{{data.age}}</p>#}    //{##}为注释信息

  {% if data.age <=19 %}  //Jinja2的if判断语句
    <p1>我小于18岁</p1>
  {% elif data.age ==18 %}
    <p1>我成年了</p1>
  {% else %}
    <p1>我老了</p1>

  {% endif %}

</body>
  • HTML读取接口返回的字典数据 {{data.name}}
  • 注释信息 {#name#}
  • {% if %} {% endif %} 判断语句 一定要有头有尾 可elif else嵌套使用
Jinja2 for in 语句
  {% endif %}

   {% for i in ['薇恩','逍遥生','九尾狐']%}
      {{I}}
      {{111}}
  {% endfor%}

  {% for key,value in data.items() %}
       {{key}}
       {{value}}
  {% endfor %}
for in
模板填充和继承
  • 首先创建一个layout.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

{% block top %}
<p>This is top </p>
{%endblock%}


{% block content %}
<p>This is content </p>
{%endblock%}

{% block foot %}
<p>This is foot </p>
{%endblock%}

</body>
</html>
  • 然后用 test.html 去导入填充数据
{% extends 'layout.html' %}   //引用模板数据
 
{% block content %}
{{ super() }}  //显示layout里的content里的内容  不写的话不显示**
这里是我的内容
{% endblock %}`
image.png
JinJa2 过滤器与管道命令
  • 管道命令| 一个管道一个管道的传值
  • default | 找不到的值才会给默认值
  • length |判断长度
{{data.school | default('内蒙古电子信息科技学院')}}  //data.school 不存在  default  只能用在不存在的内容上
{{data.name | length()}}   //判断值的长度  不能使用Length(data.name)
反向构建URL url-for
<link  rel="stylesheet" href="{{url_for('static',filename='test.css')}}">
url_for
  • 通过一些参数 构建URL好处是 修改host或者文件名和域名都不会受到影响
消息闪现、SecretyKey、变量作用域
from flask import flash
flash("王磊,你好")

test.html

{% set message = get_flashed_messages() %}
{{message}}

另外需要配置文件输入SECRET_KEY = ‘wangleinmbbnmmnb’ //随便输入


消息闪现
作用域 with endwith 作用域只能在with 和 endwith之间
{% with  message = get_flashed_messages() %}
{{message}}
{% endwith %}
项目 接下来项目就要和前端揉在一起了
  • 拷贝项目 static文件
  • 拷贝项目 templat文件
  • 拷贝项目web文件 并把文件注册到蓝图上
  • 修改base.html 71~~~79行注释掉
    修改book.py代码
@web.route('/book/search')
def search():
    form = SearchForm(request.args)

    books = BookCollection()
    if form.validate():
        q = form.q.data.strip()
        page = form.page.data
        isbn_or_key = is_isbn_or_key(q)
        yushu_book = YuShuBook()

        if isbn_or_key == 'isbn':
            yushu_book.search_by_isbn(q)
        else:
            yushu_book.search_by_keyword(q,page)

        books.fill(yushu_book,q)

        #return json.dumps(books,default=lambda o:o.__dict__),200,{"content-type":"application/json"}
    else:
        #return {"msg":"输入内容格式有误!"}
        #return form.errors
        flash('搜索的关键字不符合要求,请重新输入关键字')  //新增修改
    return render_template("search_result.html",books=books)  //新增修改

@web.route('/book/<isbn>/detail')   //新增
def book_detail(isbn):                      

    pass

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

推荐阅读更多精彩内容