python可視化利器:pyecharts

前言

前面我們提及ggplotRPython中都是數(shù)據(jù)可視化的利器,在機(jī)器學(xué)習(xí)和數(shù)據(jù)分析領(lǐng)域得到了廣泛的應(yīng)用。pyecharts結(jié)合了Python和百度開源的Echarts工具,基于其交互性和便利性得到了眾多開發(fā)者的認(rèn)可。擁有如下的特點(diǎn):

  • 可集成至FlaskDjango等主流web框架
  • 相較于matplotlib等傳統(tǒng)繪圖庫(kù)睦焕,pyecharts語(yǔ)法更加簡(jiǎn)潔,更加注重?cái)?shù)據(jù)的呈現(xiàn)方式而非圖形細(xì)節(jié)
  • 包含原生的百度地圖靴拱,方便繪制地理可視化圖形

本文主要整理自pyecharts官網(wǎng)github文檔:https://github.com/pyecharts/pyecharts/

安裝

# pip安裝
$ pip(3) install pyecharts

# 源碼安裝
$ git clone https://github.com/pyecharts/pyecharts.git
$ cd pyecharts
$ pip install -r requirements.txt
$ python setup.py install
# 或者執(zhí)行 python install.py

簡(jiǎn)單的實(shí)例

首先繪制第一個(gè)圖表:

from pyecharts.charts import Bar

bar = Bar()
bar.add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])
bar.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
# render 會(huì)生成本地 HTML 文件垃喊,默認(rèn)會(huì)在當(dāng)前目錄生成 render.html 文件
# 也可以傳入路徑參數(shù),如 bar.render("mycharts.html")
bar.render()

# pyechart所有方法均支持鏈?zhǔn)秸{(diào)用, 因此上面的代碼也可以改寫成如下形式
from pyecharts.charts import Bar

bar = (
    Bar()
    .add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])
    .add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
)
bar.render()

# 使用options配置項(xiàng)添加主標(biāo)題和副標(biāo)題
from pyecharts.charts import Bar
from pyecharts import options as opts

bar = Bar()
bar.add_xaxis(["襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子"])
bar.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
bar.set_global_opts(title_opts=opts.TitleOpts(title="主標(biāo)題", subtitle="副標(biāo)題"))
bar.render()

image.png

基本圖表

1. 柱狀圖

from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.commons.utils import JsCode
from pyecharts.globals import ThemeType

list2 = [
    {"value": 12, "percent": 12 / (12 + 3)},
    {"value": 23, "percent": 23 / (23 + 21)},
    {"value": 33, "percent": 33 / (33 + 5)},
    {"value": 3, "percent": 3 / (3 + 52)},
    {"value": 33, "percent": 33 / (33 + 43)},
]

list3 = [
    {"value": 3, "percent": 3 / (12 + 3)},
    {"value": 21, "percent": 21 / (23 + 21)},
    {"value": 5, "percent": 5 / (33 + 5)},
    {"value": 52, "percent": 52 / (3 + 52)},
    {"value": 43, "percent": 43 / (33 + 43)},
]

c = (
    # 設(shè)置主題: 默認(rèn)是黑紅風(fēng)格, 其他風(fēng)格大部分還不如黑紅風(fēng)格好看
    Bar(init_opts=opts.InitOpts())
    # 新增x軸數(shù)據(jù), 這里有五列柱狀圖
    .add_xaxis(
        [
            "名字很長(zhǎng)的X軸標(biāo)簽1",
            "名字很長(zhǎng)的X軸標(biāo)簽2",
            "名字很長(zhǎng)的X軸標(biāo)簽3",
            "名字很長(zhǎng)的X軸標(biāo)簽4",
            "名字很長(zhǎng)的X軸標(biāo)簽5",
        ]
    )
    # 參數(shù)一: 系列名稱; 參數(shù)二: 系列數(shù)據(jù); stack: 數(shù)據(jù)堆疊; category_gap: 柱間距離
    .add_yaxis("product1", list2, stack="stack1", category_gap="50%")
    .add_yaxis("product2", list3, stack="stack1", category_gap="50%")
    # set_series_opts系列配置項(xiàng)袜炕,可配置圖元樣式本谜、文字樣式、標(biāo)簽樣式偎窘、點(diǎn)線樣式等; 其中opts.LabelOpts指標(biāo)簽配置項(xiàng)
    .set_series_opts(
        label_opts=opts.LabelOpts(
            position="right",   # 數(shù)據(jù)標(biāo)簽的位置
            formatter=JsCode(   # 標(biāo)簽內(nèi)容的格式器, 這里展示了百分比
                "function(x){return Number(x.data.percent * 100).toFixed() + '%';}"
            ),
        )
    )
    # set_global_opts全局配置項(xiàng)
    .set_global_opts(
        # 旋轉(zhuǎn)坐標(biāo)軸: 解決坐標(biāo)軸名字過長(zhǎng)的問題
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
        title_opts=opts.TitleOpts(title="Bar-柱狀圖展示", subtitle="Bar-副標(biāo)題"),
    )
    .render("stack_bar_percent.html")
)
image.png

2. 特效散點(diǎn)圖

from pyecharts import options as opts
from pyecharts.charts import EffectScatter
from pyecharts.faker import Faker
from pyecharts.globals import SymbolType

c = (
    # 特效散點(diǎn)圖
    EffectScatter()
    # Faker返回假數(shù)據(jù)
    .add_xaxis(Faker.choose())
    # symbol=SymbolType.ARROW修改特效類型: 這里指箭頭特效
    .add_yaxis("", Faker.values(), symbol=SymbolType.ARROW)
    .set_global_opts(
        title_opts=opts.TitleOpts(title="EffectScatter-顯示分割線"),
        # 顯示橫縱軸分割線
        xaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True)),
        yaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True)),
    )
    .render("effectscatter_splitline.html")
)
image.png

3. 漏斗圖

研發(fā)崗涉及業(yè)務(wù)分析時(shí)經(jīng)常需要繪制漏斗圖乌助,用pyecharts可以一鍵生成


data = [[x_data[i], y_data[i]] for i in range(len(x_data))]

(
    # InitOpts初始化配置項(xiàng): 配置畫布長(zhǎng)寬
    Funnel(init_opts=opts.InitOpts(width="800px", height="500px"))
    .add(
        series_name="網(wǎng)頁(yè)訪問數(shù)據(jù)",
        data_pair=data,
        # gap: 數(shù)據(jù)圖形間距, 默認(rèn)0
        gap=2,
        # tooltip_opts: 鼠標(biāo)提示框組件配置項(xiàng), a: series_name, b: x_data, c: y_data
        tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/> : {c}%"),
        # label_opts: 標(biāo)簽配置項(xiàng), inside指標(biāo)簽在圖層內(nèi)部
        label_opts=opts.LabelOpts(is_show=True, position="inside"),
        # 圖元樣式配置項(xiàng)
        itemstyle_opts=opts.ItemStyleOpts(border_color="#fff", border_width=1),
    )
    .set_global_opts(title_opts=opts.TitleOpts(title="漏斗圖", subtitle="純屬虛構(gòu)"))
    .render("funnel_chart.html")
)
image.png

4. 關(guān)系圖

from pyecharts import options as opts
from pyecharts.charts import Graph

# 構(gòu)造數(shù)據(jù): nodes表示節(jié)點(diǎn)信息和對(duì)應(yīng)的節(jié)點(diǎn)大小; links表示節(jié)點(diǎn)之間的關(guān)系
nodes = [
    {"name": "結(jié)點(diǎn)1", "symbolSize": 10},
    {"name": "結(jié)點(diǎn)2", "symbolSize": 20},
    {"name": "結(jié)點(diǎn)3", "symbolSize": 30},
    {"name": "結(jié)點(diǎn)4", "symbolSize": 40},
    {"name": "結(jié)點(diǎn)5", "symbolSize": 50},
    {"name": "結(jié)點(diǎn)6", "symbolSize": 40},
    {"name": "結(jié)點(diǎn)7", "symbolSize": 30},
    {"name": "結(jié)點(diǎn)8", "symbolSize": 20},
]
links = []
# fake節(jié)點(diǎn)之間的兩兩雙向關(guān)系
for i in nodes:
    for j in nodes:
        links.append({"source": i.get("name"), "target": j.get("name")})
c = (
    Graph()
    # repulsion: 節(jié)點(diǎn)之間的斥力因子, 值越大表示節(jié)點(diǎn)之間的斥力越大
    .add("", nodes, links, repulsion=8000)
    .set_global_opts(title_opts=opts.TitleOpts(title="Graph-基本示例"))
    .render("graph_base.html")
)
image.png

數(shù)據(jù)分析中常見的微博轉(zhuǎn)發(fā)圖也是通過關(guān)系圖轉(zhuǎn)化來(lái)的:


image.png

5. 組合組件Grid

最常用的是組合直方圖和折點(diǎn)圖陌知。

from pyecharts import options as opts
from pyecharts.charts import Bar, Grid, Line
from pyecharts.faker import Faker

bar = (
    Bar()
    .add_xaxis(Faker.choose())
    .add_yaxis("商家A", Faker.values())
    .add_yaxis("商家B", Faker.values())
    .set_global_opts(title_opts=opts.TitleOpts(title="Grid-Bar"))
)
line = (
    Line()
    .add_xaxis(Faker.choose())
    .add_yaxis("商家A", Faker.values())
    .add_yaxis("商家B", Faker.values())
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Grid-Line", pos_top="48%"),
        legend_opts=opts.LegendOpts(pos_top="48%"),
    )
)

grid = (
    Grid()
    # GridOpts: 直角坐標(biāo)系網(wǎng)格配置項(xiàng)
    # pos_bottom: grid組件離容器底部的距離
    # pos_top: grid組件離容器頂部的距離
    .add(bar, grid_opts=opts.GridOpts(pos_bottom="60%"))
    .add(line, grid_opts=opts.GridOpts(pos_top="60%"))
    .render("grid_vertical.html")
)

image.png

6. 折線圖

import pyecharts.options as opts
from pyecharts.charts import Line
from pyecharts.faker import Faker

c = (
    Line()
    # Faker: 獲取偽造數(shù)據(jù)集
    .add_xaxis(Faker.choose())
    .add_yaxis("商家A", Faker.values())
    .add_yaxis("商家B", Faker.values())
    .set_global_opts(title_opts=opts.TitleOpts(title="Line-基本示例"))
    .render("line_base.html")
)
image.png

7. 地圖

from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker

c = (
    Map()
    # Faker: 偽造數(shù)據(jù)集, 包括國(guó)家和對(duì)應(yīng)的value
    .add("商家A", [list(z) for z in zip(Faker.country, Faker.values())], "world")
    # 顯示label
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Map-世界地圖"),
        # VisualMapOpts: 視覺映射配置項(xiàng), 指定組件的最大值
        visualmap_opts=opts.VisualMapOpts(max_=200),
    )
    .render("map_world.html")
)
image.png

8. 層疊組件

from pyecharts import options as opts
from pyecharts.charts import Bar, Line
from pyecharts.faker import Faker

v1 = [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
v2 = [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
v3 = [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]


bar = (
    Bar()
    .add_xaxis(Faker.months)
    .add_yaxis("蒸發(fā)量", v1)
    .add_yaxis("降水量", v2)
    .extend_axis(
        # 新增y坐標(biāo)軸配置項(xiàng): 因?yàn)橛腥齻€(gè)縱軸數(shù)據(jù), 包括蒸發(fā)量/降水量(單位是ml), 平均溫度(單位是°C)
        yaxis=opts.AxisOpts(
            axislabel_opts=opts.LabelOpts(formatter="{value} °C"), interval=5
        )
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Overlap-bar+line"),
        # 設(shè)置y坐標(biāo)軸配置項(xiàng)
        yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value} ml")),
    )
)

# 新增折線圖
line = Line().add_xaxis(Faker.months).add_yaxis("平均溫度", v3, yaxis_index=1)
# 使用層疊組件組合圖形
bar.overlap(line)
bar.render("overlap_bar_line.html")
image.png

9. 餅狀圖

from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker

c = (
    Pie()
    .add(
        "",
        # 設(shè)置數(shù)據(jù)集
        [list(z) for z in zip(Faker.choose(), Faker.values())],
        radius=["40%", "55%"],
        # 設(shè)置標(biāo)簽配置項(xiàng)
        label_opts=opts.LabelOpts(
            # 標(biāo)簽位置
            position="outside",
            # 標(biāo)簽內(nèi)容格式器: {a}(系列名稱)他托,(數(shù)據(jù)項(xiàng)名稱)仆葡,{c}(數(shù)值), de5tmak(百分比)
            formatter="{a|{a}}{abg|}\n{hr|}\n {b|赏参: }{c}  {per|uzvdsry%}  ",
            # 文字塊背景色
            background_color="#eee",
            # 文字塊邊框顏色
            border_color="#aaa",
            border_width=1,
            border_radius=4,
            # 在 rich 里面,可以自定義富文本樣式沿盅。利用富文本樣式把篓,可以在標(biāo)簽中做出非常豐富的效果
            rich={
                "a": {"color": "#999", "lineHeight": 22, "align": "center"},
                "abg": {
                    "backgroundColor": "#e3e3e3",
                    "width": "100%",
                    "align": "right",
                    "height": 22,
                    "borderRadius": [4, 4, 0, 0],
                },
                "hr": {
                    "borderColor": "#aaa",
                    "width": "100%",
                    "borderWidth": 0.5,
                    "height": 0,
                },
                "b": {"fontSize": 16, "lineHeight": 33},
                "per": {
                    "color": "#eee",
                    "backgroundColor": "#334455",
                    "padding": [2, 4],
                    "borderRadius": 2,
                },
            },
        ),
    )
    .set_global_opts(title_opts=opts.TitleOpts(title="Pie-富文本示例"))
    .render("pie_rich_label.html")
)

10. 雷達(dá)圖

import pyecharts.options as opts
from pyecharts.charts import Radar

"""
Gallery 使用 pyecharts 1.1.0
參考地址: https://echarts.baidu.com/examples/editor.html?c=radar

目前無(wú)法實(shí)現(xiàn)的功能:

1、雷達(dá)圖周圍的圖例的 textStyle 暫時(shí)無(wú)法設(shè)置背景顏色
"""
v1 = [[4300, 10000, 28000, 35000, 50000, 19000]]
v2 = [[5000, 14000, 28000, 31000, 42000, 21000]]

(
    Radar(init_opts=opts.InitOpts(width="1280px", height="720px", bg_color="#CCCCCC"))
    .add_schema(
        schema=[
            opts.RadarIndicatorItem(name="銷售(sales)", max_=6500),
            opts.RadarIndicatorItem(name="管理(Administration)", max_=16000),
            opts.RadarIndicatorItem(name="信息技術(shù)(Information Technology)", max_=30000),
            opts.RadarIndicatorItem(name="客服(Customer Support)", max_=38000),
            opts.RadarIndicatorItem(name="研發(fā)(Development)", max_=52000),
            opts.RadarIndicatorItem(name="市場(chǎng)(Marketing)", max_=25000),
        ],
        splitarea_opt=opts.SplitAreaOpts(
            is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
        ),
        textstyle_opts=opts.TextStyleOpts(color="#fff"),
    )
    .add(
        series_name="預(yù)算分配(Allocated Budget)",
        data=v1,
        linestyle_opts=opts.LineStyleOpts(color="#CD0000"),
    )
    .add(
        series_name="實(shí)際開銷(Actual Spending)",
        data=v2,
        linestyle_opts=opts.LineStyleOpts(color="#5CACEE"),
    )
    .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(
        title_opts=opts.TitleOpts(title="基礎(chǔ)雷達(dá)圖"), legend_opts=opts.LegendOpts()
    )
    .render("basic_radar_chart.html")
)
image.png

11. 普通散點(diǎn)圖

from pyecharts import options as opts
from pyecharts.charts import Scatter
from pyecharts.faker import Faker

c = (
    Scatter()
    .add_xaxis(Faker.choose())
    .add_yaxis("商家A", Faker.values())
    .set_global_opts(
        title_opts=opts.TitleOpts(title="Scatter-顯示分割線"),
        xaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True)),
        yaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True)),
    )
    .render("scatter_splitline.html")
)
image.png

其他圖形

其他的圖形示例可以在官方文檔中查詢:http://gallery.pyecharts.org/腰涧。

其他文章

1. 機(jī)器學(xué)習(xí)必知必會(huì)與算法原理

機(jī)器學(xué)習(xí)導(dǎo)論:什么是機(jī)器學(xué)習(xí)
機(jī)器學(xué)習(xí)必知必會(huì):凸優(yōu)化
深入淺出機(jī)器學(xué)習(xí)算法:XGBoost
機(jī)器學(xué)習(xí)必知必會(huì):梯度下降法

2. 數(shù)據(jù)分析和爬蟲案例

Python數(shù)據(jù)分析:誰(shuí)是2018當(dāng)之無(wú)愧的“第一”國(guó)產(chǎn)電影
如何用python爬蟲實(shí)現(xiàn)簡(jiǎn)單PV刷量——以CSDN為例
python腳本從零到一構(gòu)建自己的免費(fèi)代理IP池
[R]數(shù)據(jù)可視化的最佳解決方案:ggplot

3. 相關(guān)經(jīng)驗(yàn)

秋招面試:零基礎(chǔ)拿到騰訊數(shù)據(jù)崗offer需要做哪些努力
股票市場(chǎng)中如何用數(shù)據(jù)思維跑贏九成的投資者
精算師證有多難考韧掩,怎么準(zhǔn)備?

Reference

[1] http://pyecharts.org/#/zh-cn/intro
[2] http://pyecharts.herokuapp.com/bar
[3] http://gallery.pyecharts.org/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末窖铡,一起剝皮案震驚了整個(gè)濱河市疗锐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌费彼,老刑警劉巖滑臊,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異敌买,居然都是意外死亡简珠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門虹钮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)聋庵,“玉大人,你說我怎么就攤上這事芙粱〖烙瘢” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵春畔,是天一觀的道長(zhǎng)脱货。 經(jīng)常有香客問我,道長(zhǎng)律姨,這世上最難降的妖魔是什么振峻? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮择份,結(jié)果婚禮上扣孟,老公的妹妹穿的比我還像新娘。我一直安慰自己荣赶,他們只是感情好凤价,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拔创,像睡著了一般利诺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剩燥,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天慢逾,我揣著相機(jī)與錄音,去河邊找鬼灭红。 笑死氛改,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的比伏。 我是一名探鬼主播胜卤,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赁项!你這毒婦竟也來(lái)了葛躏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤悠菜,失蹤者是張志新(化名)和其女友劉穎舰攒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悔醋,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摩窃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猾愿。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鹦聪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蒂秘,到底是詐尸還是另有隱情泽本,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布姻僧,位于F島的核電站规丽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏撇贺。R本人自食惡果不足惜赌莺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望松嘶。 院中可真熱鬧艘狭,春花似錦、人聲如沸喘蟆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蕴轨。三九已至港谊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間橙弱,已是汗流浹背歧寺。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棘脐,地道東北人斜筐。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蛀缝,于是被迫代替她去往敵國(guó)和親顷链。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355