Anaconda2的安装和裁剪(Python)

[TOC]

Anaconda

简介

Anaconda 是专门为了方便使用 Python 进行数据科学研究而建立的一组软件包,涵盖了数据科学领域常见的 Python 库,并且自带了专门用来解决软件环境依赖问题的 conda 包管理系统。主要是提供了包管理与环境管理的功能,可以很方便地解决多版本python并存、切换以及各种第三方包安装问题。Anaconda利用工具/命令conda来进行package和environment的管理,并且已经包含了Python和相关的配套工具。Anaconda是一个打包的集合,里面预装好了conda、某个版本的python、众多packages、科学计算工具等等,所以也称为Python的一种发行版。

安装Anaconda

适用平台

  • Linux(x86 / Power8)
  • Windows
  • macOS

安装条件

  • 系统要求:32或64位
  • 下载文件大小:约500MB
  • 所需空间大小:3GB(Miniconda仅需要400MB)

安装步骤

  1. macOS系统安装Anaconda

  2. Windows系统安装Anaconda

  3. Linux系统安装Anaconda

    • 前往官网下载页面下载。python2.7和python3.6可供选择

    • 启动终端,在终端命令中输入命令==md5sum /path/filename 或 sha256sum /path/filename==

      • 注意:path为路径、filename为文件名
      • 建议:路径及文件名不要出现空格、中文或其他特俗字符;尽量全英文命名
    • 执行shell命令

      bash ~/downloads/Anaconda2-4.1.1-Linux-x86_64.sh
      
    • 安装过程中,看到以下提示(“请浏览许可证协议以便继续安装”),输入“enter”,查看许可证协议

      -rw-r--r-- 1 v_chyeyang v_chyeyang 419038579 Nov 10 14:42 Anaconda2-4.1.1-Linux-x86_64.sh
      [v_chyeyang@VM-147-141-centos ~/downloads]$ sh Anaconda2-4.1.1-Linux-x86_64.sh 
      
      Welcome to Anaconda2 4.1.1 (by Continuum Analytics, Inc.)
      
      In order to continue the installation process, please review the license
      agreement.
      Please, press ENTER to continue
      >>> 
      
    • 在“许可证协议”界面将屏幕滚动至底,输入“yes”表示同意许可证协议内容。然后进行下一步。

      ================
      Anaconda License
      ================
      
      Copyright 2016, Continuum Analytics, Inc.
      
      All rights reserved under the 3-clause BSD License:
      
      Redistribution and use in source and binary forms, with or without
      modification, are permitted provided that the following conditions are met:
      
      * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
      
      * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
      
      * Neither the name of Continuum Analytics, Inc. nor the names of its
      contributors may be used to endorse or promote products derived from this
      software without specific prior written permission.
      
      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      ARE DISCLAIMED. IN NO EVENT SHALL CONTINUUM ANALYTICS, INC. BE LIABLE FOR
      ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
      DAMAGE.
      
      
      Notice of Third Party Software Licenses
      =======================================
      
      Anaconda contains open source software packages from third parties. These
      are available on an "as is" basis and subject to their individual license
      agreements. These licenses are available in Anaconda or at
      http://docs.continuum.io/anaconda/pkg-docs . Any binary packages of these
      third party tools you obtain via Anaconda are subject to their individual
      licenses as well as the Anaconda license. Continuum reserves the right to
      change which third party tools are provided in Anaconda.
      
      In particular, Anaconda contains re-distributable, run-time, shared-library
      files from the Intel (TM) Math Kernel Library ("MKL binaries").  You are
      specifically authorized to use the MKL binaries with your installation of
      Anaconda.  You are also authorized to redistribute the MKL binaries with
      Anaconda or in the conda package that contains them.  If needed,
      instructions for removing the MKL binaries after installation of Anaconda
      are available at http://www.continuum.io.
      
      Cryptography Notice
      ===================
      This distribution includes cryptographic software. The country in which you
      currently reside may have restrictions on the import, possession, use,
      and/or re-export to another country, of encryption software. BEFORE using
      any encryption software, please check your country's laws, regulations and
      policies concerning the import, possession, or use, and re-export of
      encryption software, to see if this is permitted. See the Wassenaar
      Arrangement <http://www.wassenaar.org/> for more information.
      
      Continuum Analytics has self-classified this software as Export Commodity
      Control Number (ECCN) 5D002.C.1, which includes information security
      software using or performing cryptographic functions with asymmetric
      algorithms. The form and manner of this distribution makes it eligible for
      export under the License Exception ENC Technology Software Unrestricted
      (TSU) exception (see the BIS Export Administration Regulations, Section
      740.13) for both object code and source code.
      
      The following packages are included in this distribution that relate to
      cryptography:
      
      openssl
      The OpenSSL Project is a collaborative effort to develop a robust,
      commercial-grade, full-featured, and Open Source toolkit implementing the
      Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols as
      well as a full-strength general purpose cryptography library.
      
      pycrypto
      A collection of both secure hash functions (such as SHA256 and RIPEMD160),
      and various encryption algorithms (AES, DES, RSA, ElGamal, etc.).
      
      pyopenssl
      A thin Python wrapper around (a subset of) the OpenSSL library.
      
      kerberos (krb5, non-Windows platforms)
      A network authentication protocol designed to provide strong authentication
      for client/server applications by using secret-key cryptography.
      
      cryptography
      A Python library which exposes cryptographic recipes and primitives.
      
      Do you approve the license terms? [yes|no]
      >>> 
      Please answer 'yes' or 'no':
      
    • 安装过程中,提示==Press Enter to accept the default install location, CTRL-C to cancel the installation or specify an alternate installation directory==(按回车键确认安装路径,按CTRL-C取消安装或者指定安装目录)如果接受默认安装路径,则会显示PREFIX=/home/<user>/anaconda<2 or 3>并且继续安装。安装过程大约需要几分钟的时间。

      Please answer 'yes' or 'no':
      >>> yes
      
      Anaconda2 will now be installed into this location:
      /home/v_chyeyang/anaconda2
      
        - Press ENTER to confirm the location
        - Press CTRL-C to abort the installation
        - Or specify a different location below
        
      [/home/v_chyeyang/anaconda2] >>> 
      PREFIX=/home/v_chyeyang/anaconda2
      installing: python-2.7.12-1 ...
      installing: _nb_ext_conf-0.2.0-py27_0 ...
      installing: alabaster-0.7.8-py27_0 ...
      installing: anaconda-client-1.4.0-py27_0 ...
      installing: anaconda-navigator-1.2.1-py27_0 ...
      installing: argcomplete-1.0.0-py27_1 ...
      installing: astropy-1.2.1-np111py27_0 ...
      installing: babel-2.3.3-py27_0 ...
      installing: backports-1.0-py27_0 ...
      ...
      
    • 安装器若提示==Do you wish the installer to prepend the Anaconda<2 or 3> install location to PATH in your /home/<user>/.bashrc ?==(你希望安装器添加Anaconda安装路径在/home/<user>/.bashrc文件中吗?),建议输入”yes“

      注意:

      • <user>指代的是用户的家目录名
      • 如果输入”no“, 则需要手动添加环境变量,conda无法正常运
      Do you wish the installer to prepend the Anaconda2 install location
      to PATH in your /home/v_chyeyang/.bashrc ? [yes|no]
      [no] >>> yes
      
      Prepending PATH=/home/v_chyeyang/anaconda2/bin to PATH in /home/v_chyeyang/.bashrc
      A backup will be made to: /home/v_chyeyang/.bashrc-anaconda2.bak
      
    • 当看到“Thank you for installing Anaconda<2 or 3>!”则说明已经成功完成安装。

      Thank you for installing Anaconda2!
      
      Share your notebooks and packages on Anaconda Cloud!
      Sign up for free: https://anaconda.org
      
    • 关闭终端,然后再打开终端以使安装后的Anaconda启动。或者直接在终端中输入source ~/.bashrc也可完成启动。

    • 验证安装结果

      • 终端中输入==conda list== , 如果Anaconda被成功安装,则会显示已经安装的包名和版本号。
      • 终端中输入python,这条命令将会启动Python交互界面,如果Anaconda将被成功安装并且可以运行、则会在Python版本中的右边显示Anaconda custom(64-bit)

自定义裁剪

前言:Anaconda包自带conda 包管理系统、预装好某个版本的python、及众多packages、科学计算工具等等,实际开发中项目更新迭代,时常需要快速更新打包环境、却并不需要如此沉重的”发行版“,那么本文将介绍下Anaconda包安装背后的原理、及告诉我们如何进行自定义Anaconda.sh的裁剪与新增

默认安装机制

验证步骤

  • 验证文件大小,当文件字节大小不符合脚本grep时、终端停止安装

    wc -c "$THIS_PATH" | grep 419038579 >/dev/null
    if (( $? )); then
        echo "ERROR: size of $THIS_FILE should be 419038579 bytes" >&2
        exit 1
    fi
    
  • 验证操作系统如果是x86_64则继续向下执行安装,如果不是则终端停止安装

    if [[ $BATCH == 0 ]] # interactive mode
    then
        if [[ `uname -m` != 'x86_64' ]]; then
            echo -n "WARNING:
        Your operating system appears not to be 64-bit, but you are trying to
        install a 64-bit version of Anaconda2.
        Are sure you want to continue the installation? [yes|no]
    [no] >>> "
            read ans
            if [[ ($ans != "yes") && ($ans != "Yes") && ($ans != "YES") &&
                  ($ans != "y") && ($ans != "Y") ]]
            then
                echo "Aborting installation"
                exit 2
            fi
        fi
        echo -n "
    Welcome to Anaconda2 4.1.1 (by Continuum Analytics, Inc.)
    
  • 验证是否浏览许可证协议同意安装

        echo -n "
    Do you approve the license terms? [yes|no]
    >>> "
        read ans
        while [[ ($ans != "yes") && ($ans != "Yes") && ($ans != "YES") &&
                 ($ans != "no") && ($ans != "No") && ($ans != "NO") ]]
        do
            echo -n "Please answer 'yes' or 'no':
    >>> "
            read ans
        done
        if [[ ($ans != "yes") && ($ans != "Yes") && ($ans != "YES") ]]
        then
            echo "The license agreement wasn't approved, aborting installation."
            exit 2
        fi
        echo -n "
    
  • 验证默认安装目录是否存在、不存在则新建该目录,并及激活添加环境变量路径

    Anaconda2 will now be installed into this location:
    $PREFIX
    
      - Press ENTER to confirm the location
      - Press CT\
      RL-C to abort the installation
      - Or specify a different location below
    
    [$PREFIX] >>> "
        read user_prefix
        if [[ $user_prefix != "" ]]; then
            case "$user_prefix" in
                *\ * )
                    echo "ERROR: Cannot install into directories with spaces" >&2
                    exit 1
                    ;;
                *)
                    eval PREFIX="$user_prefix"
                    ;;
            esac
        fi
    fi # !BATCH
    
    case "$PREFIX" in
        *\ * )
            echo "ERROR: Cannot install into directories with spaces" >&2
            exit 1
            ;;
    esac
    
    if [[ ($FORCE == 0) && (-e $PREFIX) ]]; then
        echo "ERROR: File or directory already exists: $PREFIX" >&2
        exit 1
    fi
    
    mkdir -p $PREFIX
    if (( $? )); then
        echo "ERROR: Could not create directory: $PREFIX" >&2
        exit 1
    fi
    PREFIX=$(cd $PREFIX; pwd)
    export PREFIX
    
  • 验证文件md5值是否一致

    # verify the MD5 sum of the tarball appended to this header
    MD5=$(tail -n +417 "$THIS_PATH" | md5sum -)
    echo $MD5 | grep 3ae278d0e08ded30f07b78c0c12d5ce6 >/dev/null
    if (( $? )); then
        echo "WARNING: md5sum mismatch of tar archive
    expected: 3ae278d0e08ded30f07b78c0c12d5ce6
         got: $MD5" >&2
    fi
    

解压步骤

  1. 从安装脚本文件中获取静态pkgs二进制流,进行解压,默认释放.tar资源

    cd $PREFIX
    tail -n +417 "$THIS_PATH" | tar xf - --no-same-owner
    if (( $? )); then
        echo "ERROR: could not extract tar starting at line 417" >&2
        exit 1
    fi
    

    注意:

    • $THIS_PATH指代该安装脚本路径本身
    • —no-same-owner该参数添加后会将该包解压后的文件拥有者和所属组给到解包者,默认赋给root用户
    • 如果第一行命令执行失败、证明静态包二进制文件流起始行不对、或者本身存在问题
  2. 从解压文件中获取preconda.tar.bz2文件路径再次进行解压后删除该文件

    PRECONDA="$PREFIX/preconda.tar.bz2"
    tar xjf $PRECONDA --no-same-owner || exit 1
    rm -f $PRECONDA
    

    preconda.tar.bz2 目录:

    [v_chyeyang@VM-147-141-centos ~/tmp]$ tree preconda -a
    preconda
    └── pkgs
        ├── cache
        │   ├── 4bdb18d35809c09e4c47b552fb27cf74.png
        │   ├── 87d00fe333551440c29e16192807b6e6.png
        │   ├── 9779607c273dc0786bd972b4cb308b58.png
        │   ├── db552c1e.json
        │   └── df7feebede9861a203b480c119e38b49.png
        ├── .cio-config.py
        ├── .install.py
        ├── urls
        └── urls.txt
    
    2 directories, 9 files
    

安装步骤

  1. conda install 范例
  • 构建.tar.bz2解压方法

    extract_dist()
    {
        echo "installing: $1 ..."
        DIST=$PREFIX/pkgs/$1
        mkdir -p $DIST
        tar xjf ${DIST}.tar.bz2 -C $DIST --no-same-owner || exit 1
        rm -f ${DIST}.tar.bz2
    }
    #DIST为以该包文件名命名的目录
    extract_dist python-2.7.12-1
    
  • 测试python交付环境,如果未安装成功,则终止安装终端

    PYTHON="$PREFIX/pkgs/python-2.7.12-1/bin/python"
    $PYTHON -E -V
    if (( $? )); then
        echo "ERROR:
    cannot execute native linux-64 binary, output from 'uname -a' is:" >&2
        uname -a
        exit 1
    fi
    
  • python 执行 preconda/pkgs/.install.py完成.bz2包安装

    echo "creating default environment..."
    INSTALLPY="$PREFIX/pkgs/.install.py"
    $PYTHON -E -s $INSTALLPY --prefix=$PREFIX || exit 1
    $PREFIX/bin/python -E -s "$PREFIX/pkgs/.cio-config.py" "$THIS_PATH"
    

    注意:

    • .install.py 中需修改第44行IDISTS属性,需要添加默认安装包的md5及url
      ...
      IDISTS = {
        "python-2.7.12-1": {
          "md5": "bb956a5d1012b116dc3d89c9cf876bc5",  # 此处需要正确填写
          "url": "https://repo.continuum.io/pkgs/free/linux-64/python-2.7.12-1.tar.bz2"  # 此处需要正确填写
        }, 
          ...
        }
      ...
      
    • conda pkgs md5值及url查询网站(https://repo.anaconda.com/pkgs/free/linux-64/
  1. pip install范例

    pip_install()
    {
     echo "install: $1..."
     DIST=$PREFIX/pkgs/$1
        $PREFIX/bin/pip install ${DIST}.tar || exit 1
    }
    pip_install parameterized-0.7.4
    

    注意:

    • pip install 必须等待所有bz2安装包执行完毕后执行、当pip生效后即可直接进行pypi包进行二进制安装,eg:pip install “xxx.tar”
    • pypi官网(https://pypi.org/)查询二进制包
  2. 添加bin目录及site-packages目录到环境变量

    if [[ $BATCH == 0 ]] # interactive mode
    then
        BASH_RC=$HOME/.bashrc
        DEFAULT=no
        echo -n "Do you wish the installer to prepend the Anaconda2 install location
    to PATH in your $BASH_RC ? [yes|no]
    [$DEFAULT] >>> "
        read ans
        if [[ $ans == "" ]]; then
            ans=$DEFAULT
        fi
        if [[ ($ans != "yes") && ($ans != "Yes") && ($ans != "YES") &&
                    ($ans != "y") && ($ans != "Y") ]]
        then
            echo "
    You may wish to edit your .bashrc or prepend the Anaconda2 install location:
    
    $ export PATH=$PREFIX/bin:\$PATH
    "
        else
            if [ -f $BASH_RC ]; then
                echo "
    Prepending PATH=$PREFIX/bin to PATH in $BASH_RC
    A backup will be made to: ${BASH_RC}-anaconda2.bak
    "
                cp $BASH_RC ${BASH_RC}-anaconda2.bak
            else
                echo "
    Prepending PATH=$PREFIX/bin to PATH in
    newly created $BASH_RC"
            fi
            echo "
    For this change to become active, you have to open a new terminal.
    "
            echo "
    # added by Anaconda2 4.1.1 installer
    export PATH=\"$PREFIX/bin:\$PATH\"" >>$BASH_RC
        fi
    
        echo "Thank you for installing Anaconda2!
    
    Share your notebooks and packages on Anaconda Cloud!
    Sign up for free: https://anaconda.org
    "
    fi # !BATCH
    
    exit 0
    

裁剪上手

流程操作

  • 创建临时目录mkdir /tmp,将下载好的静态资源包放在/tmp/pkgs下,~/tmp/下资源从官方anaconda.sh中解压得来

    tmp
    ├── preconda.tar.bz2   
    ├── pkgs
    └── LICENSE.txt
    
  • 根据tar.bz2名称对应修改preconda/pkgs/.install.py文件,修改第44行IDISTS属性,同步安装包的md5及url;

    vim 打开preconda/pkgs/urls.txt同步下载地址

    ...
    IDISTS = {
      "tornado-4.3-py27_1": {
        "md5": "7c0ba8c26983e01eab473b279ade0975", # 需正确同步
        "url": "https://repo.continuum.io/pkgs/free/linux-64/tornado-4.3-py27_1.tar.bz2" # 需正确同步
      }
       #依次往下...
      }
    ...
    
  • 将~/tmp下的资源进行tar打包

    $ tar -cvf ~/tmp/ tmp.tar -C ~/
    
  • 拼接自定义裁剪脚本

    # 1.复制原 anaconda.sh 脚本内容到@@END_HEADER@@所在下一行
    head -n <nums> source_anaconda.sh >> target_anaconda.sh
    # 2.追加静态包压缩文件二进制流到目标脚本
    cat ~/tmp.tar >> target_anaconda.sh
    
  • 查看文件字节流大小

    $ ll
    total 938820
    -rw-rw-rw-  1 v_chyeyang v_chyeyang 500592001 Nov  3 18:48 Anaconda2-2019.10-Linux-x86_64.sh
    -rw-r--r--  1 v_chyeyang v_chyeyang 419038579 Nov  2 20:28 Anaconda2-4.1.1-Linux-x86_64.sh
    -rw-rw-rw-  1 v_chyeyang v_chyeyang  41679623 Nov  5 11:43 Anaconda2-4.1.1-Linux-x86_64_torch.sh
    
  • 查看文件md5值,在终端中输入==md5sum /path/filename 或 sha256sum /path/filename==

    $ md5sum Anaconda2-4.1.1-Linux-x86_64_torch.sh 
    bc1dde511dabe99007175dc79200dc4b  Anaconda2-4.1.1-Linux-x86_64_torch.sh
    
  • vim打开targe_anaconda.sh文件分别修改第60、62行及251行,同步最新的文件size和文件md5保存

    # verify the size of the installer 
    wc -c "$THIS_PATH" | grep <size> >/dev/null
    if (( $? )); then
        echo "ERROR: size of $THIS_FILE should be <size> bytes" >&2
        #exit 1
    fi
    
    # verify the MD5 sum of the tarball appended to this header
    MD5=$(tail -n +<nums> "$THIS_PATH" | md5sum -)
    echo $MD5 | grep <md5value> >/dev/null
    if (( $? )); then
        echo "WARNING: md5sum mismatch of tar archive
    expected: <md5value>
         got: $MD5" >&2
    fi
    

    注意:

    • <nums>需要从文件内容”==@@END_HEADER@@==”下一行开始计算
  • 执行脚本,裁剪包安装成功

    sh ~/target_anaconda.sh
    

常见问题

1. .install.py文件未同步

2. 文件大小及md5值脚本未同步

3. 静态包版本未正确匹配

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

推荐阅读更多精彩内容