单细胞转录组流程二:超详细! Seurat打通单细胞常规流程

Seurat standard pipeline(10核心流程)

创建Seurat对象 Read10X CreateSeuratObjecet
质控 PercentageFeatureSubject subset
标准化Normalization NormalizeData
高变基因选择 FindVariableFeatures
数据缩放 ScaleData
线性降维 RunPCA
维数选择 FindNeighbors
细胞聚类 FindClusters
非线性降维(UMAP/tSNE)RunUMAP DimPlot
鉴定差异表达特征(cluster markers)
细胞注释 CellMarker---FeaturePlot---RenameIdents

一、安装及载入

tips: Seurat 包如今已经到了 4.0 版本,R4.0 以上才可以安装。

""" 我的测试install.packages("Seurat")无法成功"""
    #建议下载安装时更换成国内镜像,例如:
options(repos="http://mirrors.tuna.tsinghua.edu.cn/CRAN/")  
options(BioC_mirror="http://mirrors.tuna.tsinghua.edu.cn/bioconductor/")
if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager")  #安装管理工具包BiocManager
BiocManager::install()  #查看是否安装成功
BiocManager::install("Seurat") 

"""如若安装不成功,请尝试"""
install.packages('remotes')
remotes::install_github(repo = 'satijalab/seurat', ref = 'develop')
library(Seurat)

"""如果上述步骤尝试不可行,请尝试下面方法用conda安装R及Seurat"""
#创建r4的虚拟环境
conda create -n r4 r-base=4.1.2
conda install r-seurat (安装的版本为4.1.1)
"""用conda 安装的R包将储存在~/miniconda3/envs/r4/lib/R/library"""

二、数据导入

自己的数据cellranger之后在outs文件夹中是三个标准文件barcodes.tsv.gzfeatures.tsv.gzmatrix.mtx.gz,但挖掘公共单细胞数据集时,会遇到常见各种单细胞测序数据格式。

(1)标准10Xgenomics类型:barcodes.tsv.gzfeatures.tsv.gz``matrix.mtx.gz

(2)表达矩阵

(3)h5

(4)h5ad

格式一:barcodes.tsv.gzfeatures.tsv.gzmatrix.mtx.gz

  • 这是cellranger上游比对分析产生的3个文件,分别代表细胞标签(barcode)、基因ID(feature)、表达数据(matrix)
  • 一般先使用read10X()对这三个文件进行整合,得到行为基因、列为细胞的表达矩阵(为稀疏矩阵dgCMatrix格式,节约内存,是未标准化的数据,如原始计数或TPMs);之后再配合CreateSeuratObject()函数创建Seurat对象
  • 示例数据集:GSE166635



    创建代码如下

dir="./data/HCC2/filtered_feature_bc_matrix/"
list.files(dir)
#[1] "barcodes.tsv.gz" "features.tsv.gz" "matrix.mtx.gz" 
counts <- Read10X(data.dir = dir)
class(counts)
#[1] "dgCMatrix"
#attr(,"package")
#[1] "Matrix"
scRNA <- CreateSeuratObject(counts = counts)
scRNA
#An object of class Seurat 
#33694 features across 9112 samples within 1 assay 
#Active assay: RNA (33694 features, 0 variable features)
  • 如上Read10X()函数接受的参数为目录名,该目录包含了所需的三个配套文件;值得注意的是三个文件名只能分别是barcodes.tsv.gzfeatures.tsv.gzmatrix.mtx.gz,然后read10X函数可以自动加载。如上截图那样就是需要修改的~

关于barcodes.tsv.gzfeatures.tsv.gzmatrix.mtx.gz三个文件的格式与内容

  • 一般来说直接使用read10X()不会出现什么问题,但有一些数据集,比如GSE148192容易出现报错。
dir = "./GSE148192_RAW/GSM4462451/"
list.files(dir)
#[1] "barcodes.tsv.gz" "features.tsv.gz" "matrix.mtx.gz"
counts =  Read10X(dir)
#Error in dimnamesGets(x, value) : 
#  invalid dimnames given for “dgTMatrix” object
  • 所以这个GSE ID提供的数据格式可能是有点问题,接下来就通过对比GSE166635的GSM5076750(可以正常读入)与GSE148192的GSM4462451(读入失败),探索下这三个文件的格式

(1)barcodes.tsv.gz

  • GSM5076750的格式:如下看出就简单的一列,为细胞的barcode标签信息


    GSM5076750
  • GSM4462451的格式:如下看出,区别在于多了行名,以及三列细胞注释信息


    GSM4462451

(2)features.tsv.gz

  • GSM5076750的格式:如下可以看出均为基因的注释信息,前两列为基因ID


  • GSM4462451的格式:如下看出,区别在于同样多了行名,以及额外两列信息


(3)matrix.mtx.gz

  • GSM5076750的格式:如下(前三行为注释信息,其中第三行为total number genes、cells、counts),结合上述细胞标签与基因名信息,知道了前两列分别为基因和细胞的索引,第三列为表达信息。
    利用这种方式实现了高效的储存数据(值得借鉴学习)。以第四行为例:表示barcodes.tsv.gz文件里第一个细胞的features.tsv.gz第33665个基因的counts数为22。
  • GSM4462451的格式:如下看出,区别有两点:第一列为细胞索引、第二列为基因索引,并且第3列是非整型数据。

    经过一番探索,将GSM4462451的barcodes.tsv.gzfeatures.tsv.gz行名删除;matrix.mtx.gz的第一列与第二列调换,第三列改为整型后,read10X()便可以顺利都成功。我认为GSM4462451这几个文件应该是作者自己制作的,吐槽一下~~。不过了解了一番这三个文件的格式也是有所收获。

格式二:直接提供表达矩阵

这种是最方便的,直接创建Seurat即可
示例数据:GSE144320


scRNA <- CreateSeuratObject(counts = counts)
scRNA

格式三:h5格式文件

  • 使用Read10X_h5()函数,读入表达矩阵,在创建Seurat对象
  • 示例数据:GSE138433


sce <- Read10X_h5(filename = GSM4107899_LH16.3814_raw_gene_bc_matrices_h5.h5")
sce <- CreateSeuratObject(counts = sce)

格式四:h5ad格式

  • 需要安装,使用SeuratDisk包的两个函数;
  • 先将后h5ad格式转换为h5seurat格式,再使用LoadH5Seurat()函数读取Seurat对象。
  • 示例数据集:GSE153643
#remotes::install_github("mojaveazure/seurat-disk")
library(SeuratDisk)
Convert("GSE153643_RAW/GSM4648565_liver_raw_counts.h5ad", "h5seurat",
        overwrite = TRUE,assay = "RNA")
scRNA <- LoadH5Seurat("GSE153643_RAW/GSM4648565_liver_raw_counts.h5seurat")

不管是哪种格式,最后都要获得的是一个稀疏矩阵:行为基因名,列为barcode(至于barcode到底是注释到什么细胞类型,这个一般公共数据是不会有的,barcode只能帮助我们对不同的细胞进行区分)

三、创建分析对象

使用 CreateSeuratObject 创建对象。

sce <- CreateSeuratObject(counts,min.cells = 10,min.features = 200)
过滤检测 min.features = 200:一个细胞最少要检测到200个基因,min.cells = 3:一个基因最少得在4个细胞中表达
#其他参数解释
  counts, #未标准化的数据,如原始计数或TPMs
  project = "CreateSeuratObject",#设置Seurat对象的项目名称
  assay = "RNA", #与初始输入数据对应的分析名称
  names.field = 1,#对于每个cell的初始标识类,从cell的名称中选择此字段。例如,如果cell在输入矩阵           #中被命名为BARCODE_CLUSTER_CELLTYPE,则设置名称。字段设置为3以将初始标识设置为          #CELLTYPE。
  names.delim = "_", #对于每个cell的初始标识类,从cell的列名中选择此分隔符。例如,如果cell命名       #为bar - cluster - celltype,则将此设置为“-”,以便将cell名称分离到其组成部分         #中,以选择相关字段。
  meta.data = NULL, #要添加到Seurat对象的其他单元级元数据。应该是data.frame,其中行是单元格名称,列     #是附加的元数据字段。

这里还涉及到的知识点是R data中的S3类和S4类
list一般情况下被认为是S3类,S4是指使用slots储存数据的格式。

> sce
An object of class Seurat 
13714 features across 2700 samples within 1 assay 
Active assay: RNA (13714 features, 0 variable features)
#1个数据集,包含2700个细胞,13714个基因。
# 查看这三个基因的前三十行矩阵
counts[c("CD3D", "TCL1A", "MS4A1"), 1:30]
> counts[c("CD3D", "TCL1A", "MS4A1"), 1:30]
3 x 30 sparse Matrix of class "dgCMatrix"
   [[ suppressing 30 column names ‘AAACATACAACCAC-1’, ‘AAACATTGAGCTAC-1’, ‘AAACATTGATCAGC-1’ ... ]]
                                              
CD3D  4 . 10 . . 1 2 3 1 . . 2 7 1 . . 1 3 . 2
TCL1A . .  . . . . . . 1 . . . . . . . . . . .
MS4A1 . 6  . . . . . . 1 1 1 . . . . . . . . .
                          
CD3D   3 . . . . . 3 4 1 5
TCL1A  . 1 . . . . . . . .
MS4A1 36 1 2 . . 2 . . . .

.在矩阵中的值表示0(未检测到分子)。由于scRNA-seq矩阵中的大多数值为0,因此Seurat在任何可能的情况下都使用稀疏矩阵表示。这为Drop-seq/inDrop/10x数据节省了大量内存和速度。所谓稀疏矩阵,也就是在矩阵中,若数值为0的元素数目远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。

四、质控过滤

常用的质控指标:
● 每个细胞在检测到的特异基因数
● 低质量细胞或空液滴通常只能检测到非常少的基因
● 两个或多个细胞被同时捕获通常会有很高的基因数
● 每个细胞检测到的分子总数(与基因密切相关)
●每个细胞的线粒体基因比例
低质量/濒死细胞常表现出广泛的线粒体污染

  使用PercentageFeatureSet()函数计算线粒体QC指标
  使用所有以MT-开头的基因作为一组线粒体基因

向sce新增一列percent.mt数据
sce[['percent.mt']] <- PercentageFeatureSet(sce,pattern='^MT-')

QC指标储存在哪?
每个细胞基因数和总分子数在建立seurat对象时就已经自动计算好了。
也可以使用sce@meta.data$percent.mt 或者 sce[['percent.mt']]查看每个细胞的线粒体比例

#展示前5个细胞的QC指标
head(sce@meta.data, 5)
> head(sce@meta.data, 5)
                 orig.ident nCount_RNA
AAACATACAACCAC-1     pbmc3k       2419
AAACATTGAGCTAC-1     pbmc3k       4903
AAACATTGATCAGC-1     pbmc3k       3147
AAACCGTGCTTCCG-1     pbmc3k       2639
AAACCGTGTATGCG-1     pbmc3k        980
                 nFeature_RNA percent.mt
AAACATACAACCAC-1          779  3.0177759
AAACATTGAGCTAC-1         1352  3.7935958
AAACATTGATCAGC-1         1129  0.8897363
AAACCGTGCTTCCG-1          960  1.7430845
AAACCGTGTATGCG-1          521  1.2244898

#使用小提琴图可视化QC指标
VlnPlot(sce, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)
#nFeature_RNA代表每个细胞测到的基因数目。
#nCount_RNA代表每个细胞测到所有基因的表达量之和。
#percent.mt代表测到的线粒体基因的比例。

FeatureScatter通常用于可视化 feature-feature 相关性,

#nCount_RNA 与percent.mt的相关性
plot1 <- FeatureScatter(pbmc, feature1 = "nCount_RNA", feature2 = "percent.mt")
#nCount_RNA与nFeature_RNA的相关性
plot2 <- FeatureScatter(pbmc, feature1 = "nCount_RNA", feature2 = "nFeature_RNA")
plot1 + plot2 #合并两图
FeatureScatter.png

拿nCounts_RNA与nFeature_RNA的散点图(scatter)来说:每个点代表一个细胞,斜率代表随着count的增加gene的增加程度。count和gene一般呈现线性关系,斜率越大也就是较少的count就可以检出较多的gene,说明这批细胞基因的丰度偏低(普遍贫穷);反之,斜率较小,说明这批细胞基因丰度较高(少数富有)。有的时候不是一条可拟合的线,或者是两条可拟合的线,也反映出细胞的异质性。总之,他就是一个散点图,描述的是两个变量的关系。

过滤线粒体基因表达比例过高的细胞,和一些极值细胞(可以根据小提琴图判断,查看两端离群值)。

sce <- subset(sce, subset = nFeature_RNA > 200 & nFeature_RNA < 7500 & percent.mt < 10)

nCount_RNA:每个细胞的UMI数量
nFeature_RNA:每个细胞的基因数
选取 2500 > nFeature_RNA >200 和percent.mt < 10的数据

五、数据标准化

因为在测序之前会对抓取到的RNA进行PCR扩增,所以需要考虑文库深度对测序的影响,所以需要对上一步得到的稀疏矩阵进行Normalize。
Normalize方式:每个细胞每个基因的特征计数除以该细胞(一列)的特征总计数,再乘以scale.factor(默认10,000),然后对结果进行log1p对数转换(log1p=log(n+1))。标准化的数值存储在sce[["RNA"]]@data中。
scale.factor = 10,000 的原因是



进行log转换的原因是:
以bulk-rna-seq为例,用FPKM或者TPM绘制热图的时候,因为数值变化的范围太过巨大,都需要进行一个log转换,让数据压缩在一个区间内。其次,也是最重要的改变数据分布:测序数值本身不符合正态分布,log转换能让数据趋近于正态分布,以便于后续进一步分析

sce <- NormlizeData(sce,normalization.method = 'LogNormalize', scale.factor = 10000)

若所有调用的参数都是默认值,则可省去
sce <- NormalizeData(sce)

六、鉴定高变基因

接下来,计算数据集中表现出高细胞间变异的特征基因(即,它们在某些细胞中高表达,而在其他细胞中低表达)。这些基因有助于突出单细胞数据集中的生物信号。
FindVariableFeatures()函数实现。默认情况下,每个数据集返回2000个features 。这些将用于下游分析,如PCA。
高变基因方法选择vst
1.使用loss(局部加权回归)拟合平滑曲线模型
2.获取模型计算的值作为y = var.exp值
3.var.standarlized = get variance after feature standardization: (每个基因-mena)/sd后取var(),注意sd=sqrt(var.exp)
4.按照var.standalized降序排列,取前n(比如2000)个基因作为高变基因

sce <- FindVariableFeatures(sce, selection.method = "vst", nfeatures = 2000)
# 查看最高变的10个基因
top10 <- head(VariableFeatures(sce), 10)
# 画出不带标签或带标签基因点图
plot1 <- VariableFeaturePlot(sce)
plot2 <- LabelPoints(plot = plot1, points = top10, repel = TRUE)
plot1 + plot2

七、数据缩放(归一化)

线性变换(“缩放”),是在PCA降维之前的一个标准预处理步骤。ScaleData()函数功能:
转换每个基因的表达值,使每个细胞的平均表达为0
转换每个基因的表达值,使细胞间的方差为1
此步骤在下游分析中具有相同的权重,因此高表达的基因不会占主导地位
结果存储在sce[["RNA"]]@scale.data中

all.genes <- rownames(pbmc)
pbmc <- ScaleData(pbmc, features = all.genes)

做了Normalize还做scale的原因是:
normalize改变的是数据的分布,scale改变的是数据的范围。
normalize是将偏态分布转换成趋近于正态分布,sclae是将数据的分布限定在一个范围内。
R语言的Z score计算是通过[scale()]函数求得,Seurat包中ScaleData()函数也基本参照了scale()函数的功能。
scale方法中的两个参数:center和scale
*center和scale默认为真,即T或者TRUE
*center为真表示数据中心化:数据集中的各项数据减去数据集的均值。如有数据集1, 2, 3, 6, 3,其均值为3 那么中心化之后的数据集为1-3,2-3,3-3,6-3,3-3,即:-2,-1,0,3,0 *scale为真表示数据标准化:指中心化之后的数据在除以数据集的标准差,即数据集中的各项数据减去数据集的均值再除以数据集的标准差。如有数据集1, 2, 3, 6, 3,其均值为3,其标准差为1.87 那么标准化之后的数据集为(1-3)/1.87,(2-3)/1.87,(3-3)/1.87,(6-3)/1.87,(3-3)/1.87,即:-1.069,-0.535,0,1.604,0
Z score的概念是指原始数据距离均值有多少个标准差。当以标准差为单位进行测量时,Z score 衡量的是一个数值偏离总体均值以上或以下多少个标准差。如果原始数值高于均值,则 Z score得分为正,如果低于均值,则Z score为负。Z score其实是标准正态分布(Standard Normal Distribution),即平均值μ=0,标准差 σ=1 的正态分布。SND标准正态分布的直方图如下所示:


z-score分布

八、线性降维

接下来,对缩放的数据执行PCA。默认情况下,只使用前面确定的变量特性作为输入,但是如果想选择不同的子集,可以使用features参数来定义(选择高变基因)。

sce <- RunPCA(sce,features = VariableFeatures(object = sce))
Seurat提供了几种有用的方法来可视化细胞和定义PCA的特性,包括VizDimReduction、DimPlot和DimHeatmap
查看PCA结果
print(pbmc[["pca"]], dims = 1:5, nfeatures = 5)
> print(pbmc[["pca"]], dims = 1:5, nfeatures = 5)
PC_ 1 
Positive:  CST3, TYROBP, LST1, AIF1, FTL 
Negative:  MALAT1, LTB, IL32, IL7R, CD2 
PC_ 2 
Positive:  CD79A, MS4A1, TCL1A, HLA-DQA1, HLA-DQB1 
Negative:  NKG7, PRF1, CST7, GZMB, GZMA 
PC_ 3 
Positive:  HLA-DQA1, CD79A, CD79B, HLA-DQB1, HLA-DPB1 
Negative:  PPBP, PF4, SDPR, SPARC, GNG11 
PC_ 4 
Positive:  HLA-DQA1, CD79B, CD79A, MS4A1, HLA-DQB1 
Negative:  VIM, IL7R, S100A6, IL32, S100A8 
PC_ 5 
Positive:  GZMB, NKG7, S100A8, FGFBP2, GNLY 
Negative:  LTB, IL7R, CKB, VIM, MS4A7 

VizDimLoadings(pbmc, dims = 1:2, reduction = "pca")
DimPlot(pbmc, reduction = "pca")
Dimplot_PCA.png

DimHeatmap()可以方便地探索数据集中异质性的主要来源,并且可以确定哪些PC维度可以用于下一步的下游分析。细胞和基因根据PCA分数来排序。

DimHeatmap(sce, dims = 1, cells = 500, balanced = TRUE) #1个PC 500个细胞
DimHeatmap.png
DimHeatmap(sce,dims = 1:15,cells = 500,balances = TRUE) #15个PC
DimHeatmap_2.png

九、确定数据维度

主成分分析的原理非常简单,概括来说就是选择包含信息量大的维度(features),去除信息量少的“干扰”维度。所以这里会有个问题——如何知道保留几个维度是最佳的呢?我们希望通过保留尽可能少的维度来留存尽可能多的信息。Seurat有两种方法来确定维度。

JackStraw && Elboew plot
sce <- JackStraw(sce,num.replicate = 100)
sce <- ScoreJackStraw(sce,dims = 1:20)
JackStrawPlot(sce,dims = 1:20)
JackStrawPlot.png

主要看在哪个PC之后,显著性大幅下降,也就是前多少个维度包含了大部分的样本信息。【但我们的样本前20个维度都没有出现了大幅下降】

ElbowPlot(sce)

主要看PC在哪个附近有拐点(“elbow”),拐点表明大部分真实信号是在前多少个pc中捕获的。


ElbowPlot.png

综合以上方法,选择X个主成成分作为参数用于后续分析。

十、细胞聚类

Seurat使用KNN算法进行聚类。

sce <- FindNeighbors(sce,dims = 1:20)#选取前20个主成分来分类细胞
sce <- FindClusters(sce,resolution = 0.6)
#查看前5个细胞的分类ID
head(Idenes(sce),5)

十一、非线性降维(UMAP/tSNE)

sce <- RunUMAP(sce,dims = 1:20)
DimPlot(sce,reduction = 'umap')
#显示在聚类标签
DimPlot(sce,reduction = 'umap', label = TRUE)
umap.png

十二、找差异表达基因(聚类标志cluster biomarkers)

利用 FindMarkers 命令,可以找到找到各个细胞类型中与其他类别的差异表达基因,作为该细胞类型的生物学标记基因。
ident.1参数设置待分析的细胞类别
min.pct参数,在两组细胞中的任何一组中检测到的最小百分
thresh.test参数,在两组细胞间以一定数量的差异表达(平均)
max.cells.per.ident参数,通过降低每个类的采样值,提高计算速度

# cluster 1的标记基因
cluster1.markers <- FindMarkers(sce, ident.1 = 1, min.pct = 0.25)
head(cluster1.markers, n = 5)
#找出区分cluster 5与cluster 0和cluster 3的所有标记
cluster5.markers <- FindMarkers(sce, ident.1 = 5, ident.2 = c(0, 3), min.pct = 0.25)
head(cluster5.markers, n = 5)
# 找出每个cluster的标记与所有剩余的细胞相比较,只报告阳性细胞
sce.markers <- FindAllMarkers(sce, only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
sce.markers %>% group_by(cluster) %>% top_n(n = 2, wt = avg_log2FC)

十三、鉴定细胞类型

数据集的markers可以通过查阅相关文献及网站(CellMarker)人工注释,或者利用singleR自动注释。singleR 比较鸡肋,最好的办法目前还是查阅文件和cellmarker(http://biocc.hrbmu.edu.cn/CellMarker/)进行区分,比较考验个人及课题组经验及搜索能力。
比如研究多形性胶质母细胞瘤(GBM),下图中的文献给出了利用单细胞转录组测序确定胶质母细胞瘤中肿瘤、基质及免疫细胞亚群:通过scRNA测序确定了GBM中CD45-和CD45+细胞(即非免疫和免疫细胞群)。表达EGFR和iCre的簇定为肿瘤细胞。采取Johnson-Verhaak命名法标记EGFR+肿瘤簇。通过marker确定细胞类型,如Oligodendrocytes(Mog,Plp1),Microglia(P2ry12,Tmem119),Astrocytes(Aqp4),Perivascular macrophages(Cd163,Mrc1),cDC1(Xcr1)等。

image.png

那我们就可以根据文中的基因试一下:

FeaturePlot(sce,features = c('MOG','PIP1','AQP4','CD163','P2RY12','TMEM119','XCR1'),reduction = 'umap')

细胞鉴定.png

列表

Cluster ID Markers Cell Type
8 P2ry12 Microglia

十四、细胞注释

new.cluster.ids <- c("Naive CD4 T", "CD14+ Mono", "Memory CD4 T", "B", "CD8 T", "FCGR3A+ Mono", 
    "NK", "DC", "Platelet")
names(new.cluster.ids) <- levels(pbmc)
pbmc <- RenameIdents(pbmc, new.cluster.ids)
DimPlot(pbmc, reduction = "umap", label = TRUE, pt.size = 0.5) + NoLegend()
保存分析的结果
saveRDS(sce, file = "../output/sce_final.rds")

参考 【感谢!】

作者:小贝学生信
链接:https://www.jianshu.com/p/5b26d7bc37b7

作者:木舟笔记
链接:https://zhuanlan.zhihu.com/p/359020041
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

推荐阅读更多精彩内容