App的分发测试(三) —— fastlane自动化打包并上传(一)

版本记录

版本号 时间
V1.0 2018.08.26

前言

我们在做App开发的时候,开发人员开发完成以后就要交给QA进行测试了,有几种方式,一种就是将QA的测试机加到账号里面的Device里面,这个有个数限制(每种硬件类型不能超过100台,即使删除设备也不会重置),然后利用三方平台比如说蒲公英进行分发,还有一种方法就是使用TestFlight进行测试,这个专题就主要说一下App分发测试相关的内容。感兴趣的看上面几篇。
1. App的分发测试(一) —— 浅谈蒲公英平台分发测试的使用(一)
2. App的分发测试(二) —— TestFlight集成和分发测试(一)

开始

首先看一下本文写作环境

Swift 3, iOS 10, Xcode 8

上传包进行测试需要笨拙的工作:捕获大量的截图,进行Xcode配置,上传到App Store和不断的盲目工作!这是不是很费时间啊!

如果有更好的方法,那不是很好吗? 如果只有您可以运行一个命令,在所有支持的设备上自动截取所有支持的语言中的所有屏幕截图。 如果只有一个命令来上传这些屏幕截图,请生成您的配置文件并提交您的应用。 想想你节省的所有时间!

嗯,你很幸运。感谢神奇的Felix Krause,现在有一个工具可以完成所有这些以及更多! 它被称为fastlane,它将成为你最好的朋友。

在这个fastlane教程中,您将学习如何使用fastlane将应用程序部署到App Store。

注意:本教程广泛使用命令行。 虽然您不需要成为终端专家,但您需要掌握命令行的工作原理。

下面正式开始,并打开建立的工程。

mZone,您将在本教程中使用的示例应用程序,是一款简单的扑克计算器,适用于无限注德州扑克锦标赛。 它会根据您的筹码数量和当前的大注级别显示建议的操作:

在Xcode中打开项目以自己查看应用程序,然后导航到mZone Poker目标的Build Settings。 在Product Bundle Identifier字段中,您可以找到com.mZone.mZone-Poker-xxx

xxx替换为您的电子邮件地址“@”“.”,以便项目的bundle identifieriTunes Connect上的每个其他应用程序标识符不同。

要使fastlane运行并运行,需要以下内容:

  • OS X 10.9(Mavericks)或更新版本
  • Ruby 2.0或更新版本
  • Xcode命令行工具(CLT)
  • 付费Apple开发者帐户

由于fastlane是Ruby脚本的集合,因此必须安装正确版本的Ruby。 幸运的是,OS X 10.9(Mavericks)以及后来默认使用Ruby 2.0。 您可以通过打开终端并输入以下命令来确认:

ruby -v

要检查是否安装了Xcode CLT,请在终端中输入以下内容:

xcode-select --install

如果已安装Xcode CLT,您将收到此错误:command line tools are already installed, use "Software Update" to install updates。 如果没有,它将为您安装Xcode CLT

完成先决条件后,您就可以安装fastlane了。 输入以下命令:

sudo gem install -n /usr/local/bin fastlane --verbose

注意:使用El Capitan,OS X引入了System Integrity Protection,也称为Rootless,它通过限制系统访问来防止用户具有root访问权限。/ usr / local / bin仍然是可写的,这就是你在那里安装fastlane的原因。

输入系统密码后,您将在终端窗口中看到一系列活动,表明安装正在进行中。 这可能需要几分钟时间,所以可以喝杯咖啡吧。

安装完成后,您就可以设置项目以使用fastlane。 但在此之前,让我们高级看一下fastlane工具。


The fastlane Toolchain - fastlane工具链

为了发挥其魔力,fastlane将以下一套工具集中在一个屋檐下:

  • produceiTunes ConnectApple Developer Portal中创建新的iOS应用程序。
  • cert自动创建和维护iOS代码签名证书。
  • sigh创建,更新,下载和修复配置文件。
  • snapshot可自动在每台设备上获取iOS应用的本地化屏幕截图。
  • frameit将您的屏幕截图放入正确的设备框架中。
  • gym构建并打包您的iOS应用程序。
  • deliver将截图,元数据和您的应用程序上传到App Store。
  • pem会自动生成并更新您的推送通知配置文件。
  • spaceship是一个Ruby库,可以访问Apple Developer CenteriTunes Connect API
  • pilot自动化TestFlight部署并管理beta测试人员。
  • boarding邀请测试人员。
  • match使用Git匹配整个团队中的同步证书和配置文件。
  • scan会对您的应用运行测试。

您将在示例应用程序的部署过程中使用许多这些工具。

这是足够的理论 - 现在是时候将fastlane放在快车道上了!


Setting up fastlane - 设置fastlane

首先,打开终端并cd进入你的mZone项目位置。 例如,如果您已将mZone文件夹添加到桌面,则可以输入:

cd ~/Desktop/mZone

mZone设置为工作目录。

进入mZone文件夹后,输入以下命令:

fastlane init

注意:如果出现“permission denied”错误,则需要在此命令前加上sudo

接下来,输入您的Apple ID以启动该过程。

fastlane使用deliver来签署iTunes ConnectApple Developer Portal,它还会使用匹配的应用程序标识符验证您帐户中是否存在应用程序。 由于这是一个新的应用程序,它将不存在,它将需要创建。

如果你收到下面的错误:

Connection reset by peer - SSL_Connect

尝试像fastlane建议的那样更新你的ruby版本。

除非您已经使用rbenvrvm(它们是Ruby版本管理器),否则最简单的方法是通过Homebrew

首先,输入以下终端命令安装Homebrew

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

接下来,使用brew命令安装Ruby:

brew update && brew install ruby

Homebrew也可能告诉你需要运行brew link --overwrite ruby。 您可能还需要打开一个新的终端会话。 然后,再次安装fastlane而不指定安装路径:

sudo gem install fastlane --verbose

最后,再次运行fastlane init,它应该能够在iTunes Connect上创建应用程序。

您应该看到以下输出:

This app identifier doesn't exist on iTunes Connect yet, it will be created for you
This app identifier doesn't exist on the Apple Developer Portal yet, it will be created for you
Please confirm the above values (y/n)

输入“y”确认检测到的值。

由于我已经在iTunes Connect上创建了一个名为“mZone Poker”的应用程序,因此接下来会提示您:

It looks like that mZone Poker has already been taken by someone else, please enter an alternative App Name:

输入唯一的应用名称。 (类似于我对bundle ID的建议,我建议使用“mZone Poker”,然后是您的电子邮件地址“@”“.”,以确保应用名称是唯一的。)

经过一段时间(根据Apple偶尔易变的服务器的状态,只需30秒和30分钟),您将被告知您的应用程序是在iTunes Connect上创建的。

打开mZone project folder。 您会注意到您的项目现在有一个fastlane文件夹:

相关文件是:

  • Appfile,用于存储应用程序标识符和Apple ID。
  • Fastfile,用于管理您创建的用于调用某些操作的通道。
  • Deliverfile,允许您在将应用程序提交到App Store时添加所需的元数据。

mZone Project文件夹中,导航到fastlane \ metadata。 您会注意到那里有一堆文本文件,其中包含常见的App Store项目,如描述,关键字,类别等。这些文件用于设置App Store上显示的应用程序元数据信息。

打开en-US / description.txt并添加以下文本:

mZone is a simple poker calculator for No Limit Texas Hold’em tournaments that displays a recommended course of action based on your chip count and the current big blind level.

将以下内容添加到keywords.txt

Poker, Cards, Gambling

检查name.txt是否已包含应用程序的名称,然后在privacy_url.txtsupport_url.txt中键入http://www.xxxxx.com

虽然此应用程序支持法语和英语,但只存在en-US文件夹。

要解决此问题,只需复制该文件夹并将其命名为fr-FR即可。 为了保持这个fastlane教程更短,我们现在不会真正提供真正的法语翻译。 您的项目文件夹现在应如下所示:

接下来,在元数据文件夹中:

  • Copyright (c) 2016 Razeware LLC添加到copyright.txt
  • Games添加到primary_category.txt
  • Card添加到primary_first_sub_category.txt
  • Casino添加到primary_second_sub_category.txt

然后,在同一文件夹中,使用您喜欢的文本/代码编辑器创建一个名为itunes_rating_config.json的json文件,其中包含以下内容:

{
  "CARTOON_FANTASY_VIOLENCE": 0,
  "REALISTIC_VIOLENCE": 0,
  "PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0,
  "PROFANITY_CRUDE_HUMOR": 0,
  "MATURE_SUGGESTIVE": 0,
  "HORROR": 0,
  "MEDICAL_TREATMENT_INFO": 0,
  "ALCOHOL_TOBACCO_DRUGS": 0,
  "GAMBLING": 2,
  "SEXUAL_CONTENT_NUDITY": 0,
  "GRAPHIC_SEXUAL_CONTENT_NUDITY": 0,
  "UNRESTRICTED_WEB_ACCESS": 0,
  "GAMBLING_CONTESTS": 0
}

iTunes评级配置使iTunes Connect知道在所有评级标准中,该应用仅包含“frequent/intense”模拟赌博(即值= 2)。 此文件为iTunes Connect提供了所需的信息,以便为应用程序提供Apple认为合适的年龄等级。

最后,在here下载App Store图标,并将其添加到元数据目录中。

恭喜! 您已添加了提交所需的所有元数据。 是时候开始使用fastlane了。

注意:您可以在here找到这些fastlane设置的完整密钥列表。


Creating Certificates and Provisioning Profiles - 创建证书和PP文件

在您选择的文本编辑器中打开Fastfile,如果您的文本编辑器支持它们,则禁用智能引号,然后使用以下代码替换该文件的内容:

# This is the minimum version number required.
# Update this, if you use features of a newer version
fastlane_version "2.6.0"

default_platform :ios

platform :ios do

  # 1
  desc "Creating a code signing certificate and provisioning profile"
  # 2
  lane :provision do
    # 3
    produce(
      app_name: 'YOUR_UNIQUE_APP_NAME',
      language: 'English',
      app_version: '1.0',
      sku: '123abc'
    )
    # 4
    cert
    # 5
    sigh(force: true)
  end

  error do |lane, exception|
  # This block is called if there was an error running a lane.
  end

end

YOUR_UNIQUE_APP_NAME替换为您之前指定的应用名称。 您的iTC用户名和应用程序标识符将自动从Appfile加载,因此您无需在此处提供它们。

如果不再是2.6.0,也要用最新版本替换fastlane版本(由于fastlane经过良好维护和频繁更新,因此很可能不会是2.6.0)。

注意:要查找当前版本,请在终端中输入fastlane -v。如果在任何时候,fastlane告诉你更新到更新的版本,但运行sudo gem update fastlane输出“Nothing to update”,也许你正在使用的ruby管理器不是最新的。 运行gem sources --add https://rubygems.org/来安装Ruby Gems,因为它可能会生成最新的信息。

如果您之前从未见过Ruby,这对您来说可能看起来很乱,所以这就是这段代码的作用:

  • 1)提供lane的描述。 通lane是顺序任务的工作流程。
  • 2)命名此laneprovision
  • 3)使用ProduceiTunes ConnectDeveloper Portal中创建一个基本应用程序,其中包含指定的标识符,名称,语言和版本号。
  • 4)使用cert创建新的私钥和签名请求,下载并安装生成的证书,并将所有生成的文件导入钥匙串。
  • 5)使用sigh来生成配置文件。 通过指定force:true,可以在每次运行时创建新的配置文件;这可确保您始终使用正确的代码签名证书。

注意:sigh默认情况下会创建App Store分发配置文件。 如果要创建临时配置文件,则需要指定sigh(adhoc:true)。 对于开发概况,它将是sigh(development: true)。 为简单起见,您只在本教程中创建分发配置文件。

哇噢! 你现在已经创建了你的第一条lane。 保存文件,在项目文件夹中打开Terminal并输入以下命令:

fastlane provision

这告诉fastlane运行你的provision lane

大约一分钟后,fastlane会要求您提供iTunes Connect密码,该密码可以安全地存储在您计算机的钥匙串中。 输入您的密码,成功完成后,您的终端窗口应输出“fastlane summary”

注意:如果您发现任何错误,尤其是“Creation of apps of this type is not available”,请登录iTunes Connect并确保您没有等待签名的任何更新协议。

登录iTunes Connect,瞧! 您的应用已经创建。 多么酷啊?

要使用刚创建的配置文件,您必须在Xcode中进行修改。 打开mZone Poker.xcodeproj,导航到mZone Poker Target \ Build Settings \ Code Signing并将您的Provisioning Profile设置为新创建的<app ID> AppStore。 然后根据此配置文件选择您的Code Signing Identity,如下所示:

请注意,您的code signing identity将基于配置文件中可用的标识。 通过这样做,您的应用程序可以在gym构建IPA文件时使用新创建的配置文件。

导航到General,取消选择Automatically manage signing,然后将Signing (Debug)Signing (Release) 设置为您刚刚指定的相同配置文件。

只需几个命令和设置,您就可以在Dev PortaliTunes Connect中添加一个应用程序,创建配置文件并为您的应用程序签名代码。 你已经节省了几个小时的工作!


Screenshots Made Easy

提交应用时,截屏是迄今为止最乏味的任务。 您的应用程序越有用(意味着它支持的设备和语言越多),您进行屏幕截图的宝贵时间就越多!

mZone支持两种语言,英语和法语,以及四种屏幕尺寸。 如果您必须为每种语言和屏幕大小拍摄每个设备五个屏幕截图,那么这将是40个屏幕截图! 但是,使用fastlane,您可以通过运行单个命令来完成所有这些操作。

但首先,通过在终端中输入以下内容来设置快照项目:

fastlane snapshot init

Snapfile文件现在将出现在fastlane文件夹中。 Snapfile允许您指定要为其提供屏幕截图的设备和语言。

打开Snapfile并使用以下代码替换该文件的内容:

# A list of devices you want to take the screenshots from
devices([
  "iPhone 5",
  "iPhone 6",
  "iPhone 6 Plus"
])
 
# A list of supported languages
languages([
  'en-US',
  'fr-FR'
])
 
# Where should the resulting screenshots be stored?
output_directory "./fastlane/screenshots"
 
# Clears previous screenshots
clear_previous_screenshots true
 
# Latest version of iOS
ios_version '10.1'

这只是设置您要支持的设备,应用程序支持的语言,并指定当前屏幕截图目录的位置。 clear_previous_screenshots将清除以前拍摄的任何截图。

等一下......为什么iPhone 7iPhone 7 Plus不在该设备列表中? 这是因为iTunes Connect上的屏幕截图按显示尺寸分类,而不是设备;由于iPhone 6和7都有4.7英寸显示屏,iPhone 6 Plus和7 Plus都有5.5英寸显示屏,包括屏幕截图文件夹中的6和7都将在iTunes Connect中产生重复的屏幕截图。

保存文件并关闭它。

返回终端并记下运行fastlane snapshot init后出现的说明:

Open your Xcode project and make sure to do the following:
1) Add a new UI Test target to your project
2) Add the ./fastlane/SnapshotHelper.swift to your UI Test target
   You can move the file anywhere you want
3) Call `setupSnapshot(app)` when launching your app

    let app = XCUIApplication()
    setupSnapshot(app)
    app.launch()

4) Add `snapshot("0Launch")` to wherever you want to create the screenshots

这就是你接下来要做的事情。

再次在Xcode中打开mZone Poker.xcodeproj,然后导航到File \ New \ Target,在iOS选项卡的Test部分中,选择iOS UI Testing Bundle,然后点击Next \ Finish

返回mZone文件夹的fastlane目录,然后将SnapshotHelper.swift拖到Xcode中新创建的mZone PokerUITests文件夹中。

打开mZone_PokerUITests.swift,删除setUptearDown方法,然后在testExample中添加以下代码:

  // 1
  let app = XCUIApplication()
  setupSnapshot(app)
  app.launch()

  // 2
  let chipCountTextField = app.textFields["chip count"]
  chipCountTextField.tap()
  chipCountTextField.typeText("10")
  // 3
  let bigBlindTextField = app.textFields["big blind"]
  bigBlindTextField.tap()
  bigBlindTextField.typeText("100")
  // 4
  snapshot("01UserEntries")    
  // 5
  app.buttons["what should i do"].tap()
  snapshot("02Suggestion")   

此代码将有助于在应用执行中的某些点创建屏幕截图。 下面进行详细分解:

  • 1)设置测试以拍摄快照并启动应用程序。
  • 2)启动的应用程序将自动点击Chip Count文本区域(其可访问性标识符在sb中预先设置为“chip count”);然后它会自动将数字10输入该区域。
  • 3)然后,应用程序将点击Big Blind文本区域(预先设置可访问性标识符为“big blind”)并在该区域中输入数字100。
  • 4)此时拍摄快照,以生成一个屏幕截图,显示应用程序在用户条目中的外观。
  • 5)自动点击What Should I Do? 按钮,然后拍摄另一个屏幕截图以显示生成的alert。

关闭Xcode,打开Fastfile并在error do |lane, exception|上面添加以下代码:

  desc "Take screenshots"
  lane :screenshot do
    snapshot
  end

在这里,您将创建一个名为screenshot的新lane,该lane使用快照来截取您刚编辑的Snapfile指定的屏幕截图。

保存文件,返回终端并输入:

fastlane screenshot

现在观看...截图被捕获,您无需做任何其他事情! 享受跳过咕噜咕噜的工作的乐趣。

在该过程完成后,html文件screenshots.html应在屏幕截图完成时自动打开,您可以滚动浏览fastlane所采取的所有屏幕截图。

注意:为了使快照获取屏幕截图,它需要访问Snapfile中列出的设备的模拟器等效项。 如果您缺少该列表中的一个或多个设备,请转到Window \ Devices,在Xcode中添加它们。 在左下角,您可以使用+添加新的模拟器。

现在,您只需使用一个终端命令即可获得英语和法语的所有设备屏幕截图 - 它不会比这更好!

注意:如果您看到有关模糊模拟器名称的警告,则可能需要删除某些模拟器或更改Snapfile的内容。快照snapshot可以与Xcode的UI测试协同工作,为您提供应用程序特定部分的屏幕截图! 更有理由使用测试。


Creating the IPA file - 创建IPA文件

当然,您不必再创建屏幕截图,这很好,但提交过程中最耗时的部分实际上是构建和签署应用程序。 猜猜看 - fastlane也能做到这一点!

打开Fastfile并在screenshot laneend后添加以下代码:

  desc "Create ipa"
  lane :build do
    increment_build_number
    gym
  end

这将创建一个名为buildlane,它使用increment_build_number将构建数增加1(因此每个构建号对于iTunes Connect的上传要求是唯一的)和gym以创建已签名的ipa文件。

保存Fastfile,然后在终端的mZone项目目录中输入以下命令:

fastlane build

这将调用您在上面添加的build lane,以启动构建过程。 成功完成后,打开mZone Project文件夹。 你应该看到签名的ipa文件:

完成! 这一命令负责处理iOS开发中最令人沮丧和最不了解的部分。


Seamless Delivery - 无缝传递

要将屏幕截图,元数据和IPA文件上传到iTunes Connect,您可以使用已安装并作为fastlane的一部分进行初始化的交付。

打开Fastfile并在build laneend后添加以下代码:

  desc "Upload to App Store"
  lane :upload do
    deliver
  end

打开终端窗口并输入以下命令:

fastlane upload

使用此命令,fastlane将以HTML页面的形式创建预览内容。

如果一切看起来都不错,请在回答问题“Does the Preview on path ‘./Preview.html’ look okay for you? (y/n)”输入y

此时,您可以放松一下,让计算机为您完成所有工作。

成功完成该过程后,您的终端窗口应如下所示:

登录您的iTunes Connect帐户。 应上传并准备好所有屏幕截图,描述和构建版本1.0。

剩下的就是点击大的“Submit for Review”按钮,你就完成了!

等一下......所有这一切都是关于手动登录并点击一个按钮的? 我以为我们正在自动化所有的事情。

好吧,事实证明,发送可以自动提交您的应用程序以供审查!

首先,您需要更新上传lane

  desc "Upload to App Store and submit for review"
  lane :upload do
    deliver(
      submit_for_review: true
    )
  end

然后,您需要使用以下内容替换Deliverfile的内容,以便它包含提交所需的所有其他信息:

# 1
price_tier 0
# 2
app_review_information(
  first_name: "YOUR_FIRST_NAME",
  last_name: "YOUR_LAST_NAME",
  phone_number: "YOUR_PHONE_NUMBER",
  email_address: "YOUR_EMAIL_ADDRESS",
  demo_user: "N/A",
  demo_password: "N/A",
  notes: "No demo account needed"
)
# 3
submission_information({    
    export_compliance_encryption_updated: false,
    export_compliance_uses_encryption: false,
    content_rights_contains_third_party_content: false,
    add_id_info_uses_idfa: false
})
# 4
automatic_release false
# 5
app_icon './fastlane/metadata/AppIcon.png'
# 6
app_rating_config_path "./fastlane/metadata/itunes_rating_config.json"

在这里,您执行以下操作:

  • 1)将您的价格等级设置为0,表明它是一个免费的应用程序。
  • 2)在app_review_information中使用适当的值填写前四行后,app_review_information会向应用审核小组提供您的联系信息。 由于fastlane当前没有布尔响应密钥来指示不需要模拟账户,因此您可以简单地指出评论说明中不需要模拟账户。
  • 3)提交信息会在选择“Submit For Review”按钮后回答您通常提出的问题。 (您可以在here处找到其他可用的密钥。)
  • 4)将automatic_release设置为false允许您在应用程序审核接受后手动发布此版本的应用程序。
  • 5)将应用程序图标文件位置提供给fastlane
  • 6)将iTunes Rating Configuration文件位置提供给fastlane

返回终端并再次运行:

fastlane upload

几分钟后,fastlane应该表明您已成功提交您的应用以供审核,iTunes Connect应该确认!

注意:从fastlane版本1.111.0开始,即使在提交期间出现问题,文本输出也可能错误地指示您的应用已成功提交。 因此,您应始终确认您的应用在iTunes Connect中显示为等待审核。

另请注意,要从iTunes中删除mZoneyour app must have been approved by an app review

批准后,您可以暂时发布,然后在pricing and availability部分选择Remove from Sale。 然后,导航到App Information屏幕,滚动到底部并选择Delete以永久删除应用程序。


Putting it All Together

您目前拥有单独的lanes,用于provisioning,屏幕截图,构建和上传到App Store。 虽然你总是可以一个一个地调用,但是你不想这样做,对吧?

哦不,你想要一个能完成一切的命令。

打开Fastfile并在upload laneend后添加以下代码:

  desc "Provision, take screenshots, build and upload to App Store"
  lane :do_everything do
    provision
    screenshot
    build
    upload
  end

正如这条lane的描述和名称所暗示的那样,这条lane可以做到一切。

通过运行此终端命令尝试一下:

fastlane do_everything

做得好! 当你坐下来放松时,让fastlane完成所有繁重的工作。

今天,您学习了如何使用fastlane部署应用程序并节省大量时间。

fastlane还提供大量集成,让您可以自定义lanes,提供Slack的实时反馈,执行单元测试和部署TestFlight构建。

要了解有关这个神奇工具的更多信息,请查看官方fastlane网站- the official fastlane website

后记

本篇主要讲述了fastlane自动化打包上传测试包,感兴趣的给个赞或者关注~~~

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

推荐阅读更多精彩内容