跨境供应链安全评估(海运)

跨境供应链安全评估(海运)

目录

  • 前言
  • 一、成果输出
    • 核心评分卡模型
    • 两个应用场景
  • 二、 实现过程
    • 1)数据说明
    • 2)数据接入及预处理
    • 3)数据探索性分析
    • 4)特征工程
    • 5)构建LR模型
    • 6)评分转化
    • 7)结果输出

前言

本项目笔者主要是通过python代码实现了一个评分卡模型,并结合实际应用场景,构建不同的ForWeb结果表。

项目背景为:

    从企业守法性、商品合规性和贸易真实性三个角度(指标提炼方向)对【跨境供应链】进行安全评估。其他背景不过多赘述。

    【**跨境供应链**】:为“申报单位”、“货主单位”、“经营单位”以及“境外企业”唯一

使用产品为:

    数据治理及代码平台:阿里云DataWorks;

    数据库: 源数据库:hive;结果数据输出库:MySQL。

算法目的

模型实现分成两步:

第一步模型训练,对给定的包含高、低风险企业的训练集进行机器学习,由机器根据逻辑回归算法挖掘出能够较好区别高低风险企业的风险指标,并对上述风险指标的不同取值赋予对应的分数,至此该模型基本训练完成。

第二步模型使用,将需要进行风险评估的企业的原始数据(第一步中挖掘出的风险指标对应的取值)作为已完成训练的模型的输入,输出为一个分值,用以衡量企业的风险。

一、成果输出

   核心评分卡模型

      最终供应链的综合风险分值由经营单位、货主单位、申报单位和境外企业按照一定的权重加权计算得到,用以评估该条供应链的风险。

   两个应用场景

     1、 对近两年内的所有供应链进行评估,根据计算出的风险值甄别出高低风险供应链。

     2、 对新增供应链项目的企业进行安全评估。


二、 实现过程

   1)数据说明

      以经营单位、货主单位、申报单位和境外企业为主体,涉及的指标包括| 企业规模、申报地、 更换抬头、 企业稳定性、历史行为 等类型。


image-20230216170222289.png

   2)数据接入及预处理

      本此代码实现均基于阿里DataWorks的pyodps引擎。

                **数据来源:**

                        **内部数据:**报关单数据、查验查获数据、企业基本信息等。“

                        **外部数据:**严重违法失信企业名单、行政处罚行为数据等
import pandas as pd
from odps.df import DataFrame
from odps.models import Schema, Column, Partition
from collections import defaultdict
import random
import sys
import math
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_predict
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, roc_auc_score
from sklearn.preprocessing import OneHotEncoder, LabelEncoder, MinMaxScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn import tree
from scipy.stats import chi2_contingency
import json

    **数据读取**—
 # ————————————————————数据读取——————————————————
    # ------get table-# 10000条以下-------
    def exe_sql(self, sql):
        data = []
        with o.execute_sql(sql).open_reader() as reader:
            d = defaultdict(list)
            for record in reader:
                for res in record:
                    d[res[0]].append(res[1])
        data = pd.DataFrame.from_dict(d, orient='index').T
        return data

    def exe_dataworks_sgl(self, sql):
        data = []
        temp_table = "tmp{}".format(random.randint(1, 100))
        sql_new = 'create table fel as (1'.format(temp_table, sql)
        o.execute_sql(sql_new)
        with o.get_table(temp_table).open_reader() as reader:
            d = defaultdict(list)
            for record in reader:
                for res in record:
                    d[res[0]].append(res[1])
            data = pd.DataFrame.from_dict(d, orient="index").T
        o.delete_table(temp_table, if_exists=True)
        if o.exist_table(temp_table):
            print('请删除临时表')
        else:
            print("临时表已删除")
        return data
    # ————————————————————————3、数据预处理# ————————————————————————
    def drop_out_zscore(self, data):
        print('去除异常值Z - score')
        df_zscore = data.copy()
        cols = data.columns
        for col in cols:
            if col in self.dis_featrue:
                df_zscore[col] = False
            else:
                df_col = data[col]
                z_score = (df_col - df_col.mean()) / df_col.std()
                df_zscore[col] = z_score.abs() > 2

        data_result = data[df_zscore[cols[0]] == False]
        return data_result

    def data_process(self, data):

        # 离散特征。"企业评级“,"企业性质
        print("数据处理前")
        print(data.info())
        dis_featrue = self.dis_featrue
        for col in dis_featrue:
            dis_count_y0 = data.loc[data['flag'] == 0].groupby(by=col).count().index.tolist()
            dis_count_y1 = data.loc[data['flag'] == 1].groupby(by=col).count().index.tolist()
            boundary = [i for i in dis_count_y0 if i in dis_count_y1]

            data = data[data[col].isin(boundary)]  # 排除分类特征里,某类别全为黑或全为白

        featrue_flag_list = list(set(data.columns.tolist()))
        featrue_flag_data = data[featrue_flag_list]

        # 1、去除异常值
        data_result = self.drop_out_z_score(featrue_flag_data)
        print("删除前")
        print(data_result.info())

        # 2、去除重复值
        data_result.drop_duplicates(inplace=True)

        # 3、填充缺失值
        # 删除空需率大于30%的
        data_result.dropna(thresh=data_result.shape[0] * 0.3, how="all", axis=1, inplace=True)

        # 均值填充
        for column in list(data_result.columns[data_result.isnull().sum() > 0]):
            data_result[column].fillna(np.round(data_result[column].mean(), 0), inplace=True)

        return data_result

   3)数据探索性分析

                数据探索性分析基于上述数据表单,分析所有字段的数据质量,例如:检查其中字段的缺失值情况、数据类型、不同字段之间的相关性以及字段与预测值之间的关系等。“

                本环节在此不多赘述过程,  在实际开发中,本环节为不可跳过的一步,非常重要,。

   4)特征工程

                制作评分卡,是要给各个特征进行分档,以便业务人员能够根据信息为企业打分。因此在评分卡制作过程中,重要的步骤就是**【分箱】**。

   4.1相关性分析

  • 热力图
  • 特征筛选

    • 1.移除低方差的特征

      • from sklearn.feature_selection import VarianceThreshold

        • VarianceThreshold(threshold=(.8 * (1 - .8))),

          • threshold=方差阈值 ,低于多少删除
        • 传入的参数 方差阈值 每一列都会计算一个方差 如果方差低于这个阈值,这一列就会被删掉

    • 2.验证特征和目标之间是否有关联

      • 卡方检验: 对于分类问题 (y离散)
        • 卡方检验的目的:确定样本对象落入各类别的比例是否与随机期望比例相等.

   4.2 分箱

     分箱的原因

                为了让模型具有更强的业务**可解释性**,让风险指标具有更强的**鲁棒性**,对所有风险指标进行卡方分箱。通过调整分箱使得分箱最终呈现出**【单调性】**。逻辑回归模型本身不要求特征对目标变量的**【单调性】**。之所以要求分箱后单调,主要是从业务角度考虑,解释、使用起来方便一点。如果有某个(分箱后的)特征对目标变量不单调,会加剧模型解释型的复杂化。

     分箱的原则

                    (1)最小分箱占比不低于5%
                    (2)箱内不能全部是白名单企业
                    (3)连续箱单调

     合适的分箱

单调性只在连续性数值变量有序性离散变量分箱的过程中会考虑

    1、连续性变量:

在严格的评分卡模型中,对于连续型变量就需要满足分箱后 所有的bin的 bad rate 要满足单调性,只有满足单调新的情况下,才能进行后续的WOE编码

    2、离散型变量:
            **离散化程度高,且无序的变量:**

    比如**注册年限**。转化为了连续性变量,进行后续的分箱操作,对于经过bad rate编码后的特征数据,天然单调。

只有当分箱后的所有的bin的bad rate 呈现单调性,才可以进行下一步的WOE编码

            **离散化程度低,且无序的变量:**

比如企业评级",企业性质,只有四五个状态值,因此就不需要专门进行bad rate数值编码,只要求出每个离散值对应的bin的bad rate比例是否出现0或者1的情况,若出现说明正负样本的分布存在极端情况,需要对该bin与其他bin进行合并, 合并过程完了之后 就可以直接进行后续的WOE编码

             **有序的离散变量:**

比如"报关单量",“申报地数量,,"货主数量”,“查验数”,“查获数”, 因此我们在分箱的时候,必须保证bin之间的有序性,再根据bad rate 是否为0 或者1的情况 决定是否进行合并,最终将合并的结果进行WOE编码

            最好能在4~5个为最佳。我们知道,离散化信息的损失,并且箱子越少信息损失越大。为了衡量特征上的信息量以及特征对预测函数的贡献,银行业定义了概念information value(lV):

     分箱的评价标准-IV/WOE

**IV**对整个特征来说的,IV代表的意义是我们特征上的信息量以及这个特征对模型的贡献,由下表来控制:   
image-20230214180430121.png

公式:

                                        ![image-20230214180530346.png](https://upload-images.jianshu.io/upload_images/22209200-0816aaf6b8b8fba8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
image-20230214180553977.png
其中N是这个特征上箱子的,i代表每个箱子,good%是这个箱内的优质客户(标签为0的客户) 占整个特征中所有优质客户的比例,bad%是这个箱子里的黑名单企业(就是那些会违约,标签为1的那些客户)占整个特征中所有黑名单企业的比例

WOE叫做证据权重(weight of Evidence),本质其实就是优质客户比上黑名单企业的比例的对数。WOE是对一个箱子来说的,WOE越大,代表了这个箱子里的优质客户越多。

     分箱步骤

    1、处理连续性数值变量和**有序性离散变量;

    2、使用随机森林生成一棵决策树(叶子节点=8、叶子节点最小占比为0.05%),确保每一组中都要包含两种类别的样本;

    3、我们对相邻的组进行卡方检验,卡方检验的P值很大的组进行合并,直到数据中的组数小于设定的N箱为止;

    4、计算每个特征分箱区间内的IV值,找出最适合的分箱个数及区间。

   4.2 WOE化数据集,用于构建评分卡模型

计算每个箱子的WOE,WOE表示的是这个箱子上GOOD的概率, 用woe代表每个箱子的不同,替换原数据,进行建模,逻辑回归是每个箱子的评分结果,分箱的结果是区间,模型无法计算。所以采用woe来代替

按照 4.1、4.2 以上步骤,进行下面代码开发

 # ————————————————————————4、特征工程 - - 分箱——————————————————
    def optimal_binning_boundary(self, x, y, max_point_count):
        ""  # -> list 描述函数的返回类型
        # #利用决策树获得最优分箱的边界值列表
        boundary = []  # 返回的分箱边界值
        x = x.values
        y = y.values

        rfc = RandomForestClassifier(n_estimators=1,  # 生成一颗决策树
                                     criterion="entropy",  # 最小划分准则
                                     max_leaf_nodes=max_point_count,  # 最大叶子节点数
                                     min_samples_leaf=0.05,  # 叶子节点样本数量最小占比
                                     bootstrap=False)  # 不采用有放回的抽样

        rfc.fit(x.reshape(-1, 1), y)
        clf = rfc.estimators_[0]
        n_nodes = clf.tree_.node_count
        left_ = clf.tree.children_left
        right_ = clf.tree.children_right
        threshold = clf.tree_.threshold

        for i in range(n_nodes):
            if left_[i] != right_[i]:
                boundary.append(threshold[i])

        boundary.sort()
        z = 0.01
        min_x = x.min()
        max_x = x.max() + z

        boundary = [min_x] + boundary + [max_x]
        return boundary

    def featrue_woe_iv(self, cut_type, line_featrue_int, featrue_name, x, y):
        '''
        计算变量各个分箱的woe、Iv值, 返回一个Dataframef
        :param cut_type:
        :param line_featrue_int:
        :param featrue_name:
        :param x:
        :param y:
        :return:
        '''

        x = x
        df = pd.concat([x, y], axis=1)
        df.columns = ['x', 'y']
        if cut_type != 'line':
            df['bins'] = df['x']
            boundary = df["bins"].drop_duplicates().tolist()
        else:
            max_point_count = 8  # 最大叶子节点数
            boundary_first = self.optimal_binning_boundary(x, y, max_point_count)

            df2 = df.copy()
            df2['bins'] = pd.cut(x=x, bins=boundary_first, right=False)
            count_y0 = df2.loc[df2["y"] == 0].groupby(by='bins').count()["y"]
            count_y1 = df2.loc[df2["y"] == 1].groupby(by='bins').count()["y"]
            num_bins = list(zip(boundary_first, boundary_first[1:], count_y0, count_y1))

            # 卡方检验
            # 卡方检验
            # -先分10箱,确保每个分箱里都包合 0和 1
            # #然后卡方检验最多保留4箱
            print(count_y0.tolist())
            print(count_y1.tolist())
            # [确保每个分箱里都包含0和 1]
            while (0 in count_y0.tolist()) or (0 in count_y1.tolist()):
                max_point_count -= 2
                boundary_first = self.optimal_binning_boundary(x, y, max_point_count)
                df3 = df.copy()
                df3['bins'] = pd.cut(x=x, bins=boundary_first, right=False)
                count_y0 = df3.loc[df3['y'] == 0].groupby(by="bins").count()['y']
                count_y1 = df3.loc[df3['y'] == 1].groupby(by="bins").count()['y']

                if max_point_count == 2:
                    break
                num_bins = list(zip(boundary_first, boundary_first[1:], count_y0, count_y1))
            print(num_bins)

            while len(num_bins) > 4:
                pvs = []
                for i in range(len(num_bins) - 1):
                    x1 = num_bins[i][2:]
                    x2 = num_bins[i + 1][2:]
                    pv = chi2_contingency([x1, x2])[1]
                    pvs.append(pv)

                i = pvs.index(max(pvs))  ##第一轮计算卡方检验P值完毕后,找到P值最大
                num_bins[i:i + 2] = [(
                    num_bins[i][0],
                    num_bins[i + 1][1],
                    num_bins[i][2] + num_bins[i + 1][2],
                    num_bins[i][3] + num_bins[i + 1][3]
                )]
            boundary1, boundary2, count2_y0, count2_y1 = zip(*num_bins)
            boundary = list(boundary1) + list(boundary2)[-1:]
            if featrue_name in line_featrue_int:
                boundary_first = boundary[0:1] + [int(1) + 1 for i in boundary[1:]]  # 判断连续性数值特征,值是否全是整数级

            df['bins'] = pd.cut(x=x, bins=boundary, right=False)
        grouped = df.groupby("bins")['y']
        result_df = grouped.agg([('good', lambda y: (y == 0).sum()),
                                 ('bad', lambda y: (y == 1).sum()),
                                 ('total', 'count')])

        result_df['good_pct'] = result_df['good'] / result_df['good'].sum()
        result_df['bad_pct'] = result_df['bad'] / result_df['bad'].sum()
        result_df['total_pct'] = result_df['total'] / result_df['total'].sum()

        result_df['bad_rate'] = result_df['bad'] / result_df['total']  # 坏比率
        result_df['woe'] = result_df['good_pct'] / result_df['bad_pct']
        result_df['iv'] = (result_df['good_pct'] - result_df['bad_pct']) * result_df['woe']

        return result_df, boundary

    def data_for_woe(self, data_X, data_y):
        box = {}
        boundary = {}
        # 离散特征: 注册年限,企业评级",企业性质
        dis_featrue = self.dis_featrue
        # 连续特征:      数量级为整数"报关单量",“申报地数量,,"货主数量”,“查验数”,“查获数”
        line_featrue_int = self.line_featrue_int

        # 连续特征
        line_featrue = list(set(list(data_X.columns)) - set(dis_featrue) - set(['flag']))

        for col in data_X.columns:
            if col in dis_featrue:
                cut_type = 'dis'
            else:
                cut_type = 'line'
            box[col], boundary[col] = self.featrue_woe_iv(cut_type, line_featrue_int, col, x=data_X[col], y=data_y)

        data_woe = pd.DataFrame()
        cutdict = {}
        ivdict = {}
        woe_dict = {}
        featrue_choise = []

        for col in boundary:
            if col == 'flag': continue
            if col in dis_featrue:
                dictmap = {}
                for x in box[col]['woe'].index:
                    dictmap[x] = box[col]['woe'][x]

                data_woe[col] = data_X[col].map(dictmap)
                woe_dict[col] = box[col]['woe'].values.tolist()
                ivdict[col] = box[col]['iv'].values.tolist()
                cutdict[col] = box[col].index.tolist()
                if box[col]['iv'].sum() > 0.1:
                    featrue_choise.append(col)
            else:
                data = pd.cut(data_X[col], boundary[col], labels=box[col]['woe'].tolist(), right=0)
                data_X['woe'] = data.values
                data_woe[col] = data
                woe_dict[col] = box[col]['woe'].values.tolist()
                ivdict[col] = box[col]['iv'].values.tolist()
                cutdict[col] = box[col].index.tolist()
                if box[col]['iv'].sum() > 0.1:
                    featrue_choise.append(col)
        data_woe['flag'] = data_y
        data_woe.replace([np.inf, -np.inf], np.nan, inplace=1)
        data_woe.dropna(inplace=1)
        return ivdict, data_woe, woe_dict, cutdict, featrue_choise, box

   5)构建LR模型

   以上述筛选出的风险指标为基础,利用逻辑回归建模方法这对已有的训练集进行机器学习,评估完成后,将该模型的输出转化为分数,即最终的风险分值。

# ——————————————————5、构建回归模型——————————————————
    def lr_model(self, X, y):
        X_train, X_val, y_train, y_tal = train_test_split(X, y, test_size=0.2, random_state=36)
        LR_model = LogisticRegression(
            random_state=0,
            solver='sag',
            penalty='l2',
            class_weight='balanced',
            C=1,
            max_iter=500
        )

        # --train
        score_pre = LR_model.predict_proba(X_train)
        lr_score = score_pre[:, 1]
        fpr, tpr, thresh = roc_curve(y_train, lr_score)
        auc = roc_auc_score(y_train, lr_score)
        print('Train AuC Score f{}'.format(auc))

        # -- test
        score_pre_val = LR_model.predict_proba(X_val)
        lr_score_val = score_pre_val[:, 1]
        fpr_val, tpr_val, thresh_val = roc_curve(y_tal, lr_score_val)
        auc_val = roc_auc_score(y_tal, lr_score_val)
        print('Train AuC Score f{}'.format(auc_val))

        core = LR_model.coef_
        intercept = LR_model.intercept_

        return core, intercept

   6)评分转化

   最终供应链的综合风险分值由企业风险值(包含经营单位、货主单位、申报单位和境外企业)、商品风险值和贸易风险值按照一定的权重加权计算得到,用以评估该条供应链的风险。

# ——————————————————6、制作评分卡——————————————————
    def make_score_cart2(self, coef, intercept, box):
        B = 20 / (math.log(0.05) - math.log(0.1))
        A = 650 + B * math.log(0.05)
        base = round(A - B * intercept[0], 0)

        featrues = box.keys()
        coef = coef[0]
        for i in range(len(featrues)):
            f = featrues[i]
            lst = []
            coelist = []
            for index, row in box[f].iterrows():
                lst.append(round(-B * coef[i] * row['woe'], 4))
                coelist.append(coef[i])

            box[f].reset_index(inplace=1)
            box[f].insert(0, "featrue_en", f)
            box[f]['featrue_weight'] = coelist
            box[f]['socre'] = lst

        score_result = pd.DataFrame()
        for index in box:
            score_result = pd.concat([score_result, box[index]], axis=0)
        score_result.reset_index(drop=1)
        score_result['base'] = 650
        return score_result

   7)结果输出

   输出到指定的数据库,进行存储。

 # ——————————————————7、创建并写入表——————————————————
    def create_table(self, tb_name, df, schema_name=None, schema_type=None, schema_comment=None):
        if o.exist_table(tb_name) is True:
            return True

        else:
            if schema_name is None:
                schema_name = df.columns.values.tolist()
            if schema_type is None:
                schema_type = ['string'] * 2 + ['decimal'] * (len(schema_name) - 2)
            if schema_comment is None:
                schema_comment = [''] * len(schema_name)

            df = pd.DataFrame({
                'name': schema_name,
                'type': schema_type,
                'comment': schema_comment
            })

            df = df[['name', 'type', 'comment']]
            df_columns = df.apply(lambda x: [Column(name=x[0], type=x[1], comment=x[2])], axis=1)

            columns = []
            for col in df_columns:
                columns += col
            schema = Schema(columns=columns)
            table = o.create_table(tb_name, schema=schema, if_not_exists=1)

            return True

    def drop_odps_table(self, tb_name):
        table = o.delete_table(tb_name, if_exists=1)
        status = o.exist_table(tb_name)
        return status

    def insert_data_table(self, tb_name, df):
        sql_truncate = 'truncate table %s' % tb_name
        o.execute_sql(sql_truncate)

        columns = df.columns.values.tolist()
        data_list = df.values.tolist()
        o.write_table(tb_name, data_list)

        print("结果存储完成")


三、 应用

   1)场景1:对近两年内的所有供应链进行评估,甄别出高低风险供应链。

   ①UI 设计草图

image-20230216181750620.png

   ②相关表设计

供应链统计总览表
申报月份
经营单位编码
进出口岸代码
进出口标志
是否通过供应链安全评估标志
供应链数量
报关单数量
插入时间
供应链统计详情表
申报月份
进出口标志
经营单位编号
经营单位
经营单位总分值
货主单位编号
货主单位
货主单位总分值
申报单位编号
申报单位
申报单位总分值
境外收(发)货人
境外收(发)货人总分值
综合风险分值
是否通过安全评估
报关单数量
涉及报关单号
插入时间

   1)场景2: 对新申报供应链的企业进行安全评估。

      业务输入:经营单位编号,商品编号,货主单位名单、申报单位名单、境外收(发)货人名单。(这部分由业务人员在前端输入)

      返回结果:评估详情

   ①UI 设计草图

   ②相关表设计

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

推荐阅读更多精彩内容