Python爬蟲(chóng)——aiohttp異步協(xié)程爬取同程旅行酒店評(píng)論

大家好铅协!我是霖hero

Python并發(fā)編程有三種方式:多線程(Threading)坏平、多進(jìn)程(Process)贬蛙、協(xié)程(Coroutine),使用并發(fā)編程會(huì)大大提高程序的效率宇弛,今天我們將學(xué)習(xí)如何選擇多線程、多進(jìn)程和協(xié)程來(lái)提高代碼的效率源请、如何使用異步協(xié)程枪芒,并用協(xié)程來(lái)獲取同程旅行酒店的評(píng)論數(shù)據(jù)彻况。

并發(fā)編程

多線程(Threading)

多線程(Threading):從軟件或者硬件上實(shí)現(xiàn)多個(gè)線程并發(fā)執(zhí)行的技術(shù)。能夠在同一時(shí)間執(zhí)行多于一個(gè)線程舅踪,進(jìn)而提升整體處理性能纽甘,利用CPU和IO可以同時(shí)執(zhí)行的原理,讓CPU不會(huì)干巴巴地等待IO完成抽碌。

工作方式:多線程由三個(gè)部分組成:新任務(wù)贷腕、任務(wù)隊(duì)列、線程咬展。由于新建線程系統(tǒng)是需要分配資源的泽裳,終止線程系統(tǒng)是需要回收資源的,為了重用線程破婆,把線程放在一個(gè)線程池中涮总,如下圖所示:

  • 線程池:里面提前建好N個(gè)線程,這些都會(huì)被重復(fù)利用祷舀;

  • 任務(wù)隊(duì)列:當(dāng)有新任務(wù)的時(shí)候瀑梗,會(huì)把任務(wù)放在任務(wù)隊(duì)列中。

當(dāng)任務(wù)隊(duì)列里有任務(wù)時(shí)裳扯,線程池的線程會(huì)從任務(wù)隊(duì)列中取出任務(wù)并執(zhí)行抛丽,執(zhí)行完任務(wù)后,線程會(huì)執(zhí)行下一個(gè)任務(wù)饰豺,直到?jīng)]有任務(wù)執(zhí)行后亿鲜,線程會(huì)回到線程池中等待任務(wù)。

多進(jìn)程(Process)

多進(jìn)程:一個(gè)程序的執(zhí)行實(shí)例就是一個(gè)進(jìn)程冤吨,每一個(gè)進(jìn)程提供執(zhí)行程序所需的所有資源蒿柳,利用多核CPU的能力,真正的并行執(zhí)行任務(wù)漩蟆。

工作方式:通過(guò)CPU調(diào)度器來(lái)并發(fā)執(zhí)行進(jìn)程垒探,如下圖所示:

協(xié)程(Coroutine)

協(xié)程:一種比多線程高效得多的并發(fā)模型,是無(wú)序的怠李,為了完成某個(gè)任務(wù)圾叼,在執(zhí)行的過(guò)程中,不同程序單元之間過(guò)程中無(wú)需通信協(xié)調(diào)捺癞,也能完成任務(wù)的方式夷蚊,在單線程利用CPU和IO同時(shí)執(zhí)行的原理,實(shí)現(xiàn)函數(shù)異步執(zhí)行翘簇。

工作方式:如下圖所示:

當(dāng)請(qǐng)求程序發(fā)送網(wǎng)絡(luò)請(qǐng)求1并收到某個(gè)站點(diǎn)的響應(yīng)后撬码,開(kāi)始執(zhí)行程序中的下載程序,由于下載需要時(shí)間或者其他原因使處于阻塞狀態(tài)版保,請(qǐng)求程序和下載程序是不相關(guān)的程序單元呜笑,所以請(qǐng)求程序發(fā)送下一個(gè)網(wǎng)絡(luò)請(qǐng)求夫否。

并發(fā)編程對(duì)比

簡(jiǎn)單了解了并發(fā)編程的三種方式,接下來(lái)將對(duì)比這三種方式的優(yōu)缺點(diǎn)并根據(jù)任務(wù)來(lái)選擇對(duì)應(yīng)的技術(shù)叫胁。

多進(jìn)程Process

  • 優(yōu)點(diǎn):可以利用多核CPU并行運(yùn)算凰慈;

  • 缺點(diǎn):占用資源最多、可啟動(dòng)數(shù)目比線程少驼鹅;

  • 適用于:CPU密集型計(jì)算微谓。

多線程threading

  • 優(yōu)點(diǎn):比進(jìn)程更輕量級(jí),占用資源少输钩;

  • 缺點(diǎn):只能并發(fā)執(zhí)行豺型,不能利用多CPU,啟動(dòng)數(shù)目有限买乃,占用內(nèi)存資源姻氨,有線程切換開(kāi)銷(xiāo);

  • 適用于:IO密集型計(jì)算剪验、同時(shí)運(yùn)行的任務(wù)數(shù)目要求不多肴焊。

協(xié)程Corutine

  • 優(yōu)點(diǎn):內(nèi)存開(kāi)銷(xiāo)最少,啟動(dòng)協(xié)程數(shù)量最多功戚;

  • 缺點(diǎn):之前的庫(kù)有限制娶眷、代碼實(shí)現(xiàn)復(fù)雜;

  • 適用于:IO密集型計(jì)算啸臀、需要超多任務(wù)運(yùn)行届宠。

有人可能不知道什么是CPU、IO密集型計(jì)算壳咕,我們來(lái)簡(jiǎn)單講解一下:

  • CPU密集型:指I/O在很短的時(shí)間就可以完成席揽,CPU需要大量的計(jì)算機(jī)和處理,CPU占用率很高谓厘,壓縮解壓、加密解密寸谜、正則表達(dá)式搜索等都屬于CPU密集型計(jì)算竟稳。

  • IO密集型:指I/O(硬盤(pán)/內(nèi)存)的讀寫(xiě)操作,CPU占用率較低熊痴,文件處理程序他爸、網(wǎng)絡(luò)爬蟲(chóng)、讀寫(xiě)數(shù)據(jù)庫(kù)都屬于IO密集型計(jì)算果善。

好了诊笤,最后通過(guò)一張圖來(lái)總結(jié)如何選擇并發(fā)編程的方式:


異步協(xié)程

asyncio模塊

asyncio模塊是Python中實(shí)現(xiàn)協(xié)程的模塊之一,其語(yǔ)法格式如下:

import asyncio
#定義協(xié)程
async def myfunc(url):
    await 響應(yīng)的數(shù)據(jù)或調(diào)用下一個(gè)方法等等
#獲取事件循環(huán)
loop=asyncio.get_event_loop()
#創(chuàng)建task列表
tasks=[loop.create_task(myfunc(url))]
#執(zhí)行爬蟲(chóng)事件列表
loop.run_until_complete(asyncio.wait(tasks))

其中:

  • async:聲明該方法是異步協(xié)程方法巾陕;

  • await:聲明為異步協(xié)程可等待對(duì)象讨跟;

  • create_task:創(chuàng)建線程任務(wù)纪他;

注意:異步協(xié)程操作不能出現(xiàn)同步操作,否則異步操作將失效或報(bào)錯(cuò)晾匠。

aiohttp庫(kù)

requests請(qǐng)求庫(kù)是不支持異步協(xié)程的茶袒,所以我們使用aiohttp請(qǐng)求庫(kù),這個(gè)請(qǐng)求庫(kù)只能發(fā)送異步請(qǐng)求凉馆,下篇文章我們學(xué)習(xí)更強(qiáng)大的異步請(qǐng)求庫(kù)httpx薪寓,httpx請(qǐng)求庫(kù)既可以發(fā)送同步請(qǐng)求,也可以發(fā)送異步請(qǐng)求澜共。

aiohttp基本使用

使用語(yǔ)法為:

import aiohttp
import asyncio
async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            print(await 響應(yīng)的數(shù)據(jù)或調(diào)用下一個(gè)方法等等)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

先導(dǎo)入aiohttp模塊和asyncio模塊向叉,aiohttp.ClientSession() 相當(dāng)于把a(bǔ)iohttp的功能傳遞給session,也就是說(shuō)語(yǔ)法中的ClientSession()相當(dāng)于aiohttp嗦董,接著我們就可以使用client來(lái)調(diào)用get請(qǐng)求調(diào)用asyncio.get_event_loop()方法進(jìn)入事件循環(huán)植康,再調(diào)用loop.run_until_complete(main())方法運(yùn)行事件循環(huán),直到main運(yùn)行結(jié)束展懈。

post請(qǐng)求

網(wǎng)頁(yè)請(qǐng)求中有兩種類(lèi)型销睁,一種是Form Data類(lèi)型和Request Playload類(lèi)型

當(dāng)我們發(fā)送post請(qǐng)求中,需要根據(jù)請(qǐng)求類(lèi)型來(lái)傳遞是否使用data參數(shù)還是使用json參數(shù)

params = [('key', 'value1'), ('key', 'value2')]
async with aiohttp.ClientSession() as session:
    #data參數(shù)
    async with session.post(url,data=params) as resp:
    ...
    #json參數(shù)
    async with session.post(url,json=params) as resp:

有時(shí)候存崖,我們URL參數(shù)構(gòu)造正確卻獲取不到數(shù)據(jù)冻记,有可能是因?yàn)閜ost請(qǐng)求中的參數(shù)選擇不正確,

那么什么時(shí)候使用data參數(shù)来惧,什么時(shí)候json參數(shù)呢冗栗?

判斷方法很簡(jiǎn)單,當(dāng)出現(xiàn)如下圖的情況時(shí)供搀,該網(wǎng)頁(yè)請(qǐng)求是Form Data類(lèi)型隅居,要使用data參數(shù):

當(dāng)出現(xiàn)如下圖情況時(shí),該網(wǎng)頁(yè)請(qǐng)求是Request Playload類(lèi)型葛虐,要使用json參數(shù):

超時(shí)

在某些情況下胎源,我們調(diào)用第三方接口時(shí),響應(yīng)時(shí)間無(wú)法估計(jì)屿脐,這時(shí)可以指定超時(shí)時(shí)間涕蚤,如果超時(shí)未處理成功,則直接跳過(guò)它的诵,繼續(xù)向下執(zhí)行万栅。aiohttp提供了ClientTimeout方法來(lái)設(shè)置超時(shí),其語(yǔ)法格式如下:

timeout=aiohttp.ClientTimeout(total=5*60, connect=None,sock_connect=None, sock_read=None)
async with aiohttp.ClientSession(timeout=timeout) as session:
    ...

默認(rèn)情況下西疤,aiohttp使用總共300 秒(5 分鐘)的超時(shí)時(shí)間烦粒,這意味著整個(gè)操作應(yīng)該在 5 分鐘內(nèi)完成。

其中:

  • total:整個(gè)操作的最大秒數(shù)代赁,包括連接建立扰她、請(qǐng)求發(fā)送和響應(yīng)讀仁揸;

  • connect:連接建立新連接或在超過(guò)池連接限制時(shí)等待來(lái)自池的空閑連接的最大秒數(shù)义黎;

  • sock_connect:連接到新連接的對(duì)等點(diǎn)的最大秒數(shù)禾进;

  • sock_read:從對(duì)等方讀取新數(shù)據(jù)部分之間允許的最大秒數(shù)。

限制連接池大小

當(dāng)我們要獲取的數(shù)據(jù)量很大時(shí)廉涕,為了提高程序效率或防止訪問(wèn)網(wǎng)頁(yè)過(guò)多造成對(duì)方網(wǎng)頁(yè)癱瘓泻云,通常情況下要設(shè)置連接池的大小,aiohttp提供了TCPConnector方法來(lái)限制連接池的大小狐蜕,其語(yǔ)法格式為:

timeout=aiohttp.ClientTimeout(total=5*60, connect=None,sock_connect=None, sock_read=None)
async with aiohttp.ClientSession(timeout=timeout) as session:
    ...

上面的設(shè)置是并行連接總數(shù)限制為30宠纯,默認(rèn)情況下限制數(shù)是100,當(dāng)我們不想設(shè)置限制數(shù)目時(shí)层释,可以把limit參數(shù)中的值改為0即可婆瓜。

好了,aiohttp請(qǐng)求庫(kù)講解到這里贡羔,接下來(lái)我們正式開(kāi)始爬取同程旅行酒店評(píng)論廉白。

實(shí)戰(zhàn)演練

這次的爬蟲(chóng)過(guò)程是:

  1. 評(píng)論數(shù)據(jù)網(wǎng)頁(yè)分析;

  2. 酒店列表網(wǎng)頁(yè)分析乖寒;

  3. 同步請(qǐng)求獲取酒店id

  4. 異步請(qǐng)求獲取酒店評(píng)論猴蹂;

  5. 保存數(shù)據(jù)到MongoDB中;

  6. 繪制詞云圖楣嘁。

評(píng)論數(shù)據(jù)網(wǎng)頁(yè)分析

隨意進(jìn)入一個(gè)酒店的詳情頁(yè)并打開(kāi)開(kāi)發(fā)者工具磅轻,如下圖所示:


經(jīng)過(guò)查找,我們發(fā)現(xiàn)評(píng)論數(shù)據(jù)保存在getCommentList數(shù)據(jù)包中逐虚,如下圖所示:



那么我們觀察一下getCommentList數(shù)據(jù)包的headers信息聋溜,如下圖所示:

請(qǐng)求方式是post請(qǐng)求,而且是Request payload類(lèi)型叭爱,所以我們?cè)谑褂胘son參數(shù)撮躁。

經(jīng)過(guò)觀察,我們發(fā)現(xiàn)objectId是酒店的id涤伐,pageIndex是翻頁(yè)參數(shù)馒胆,pageSize是每個(gè)url存放的數(shù)量,其他的參數(shù)要么是空凝果,要么是定值,所以我們只要知道酒店的id就可以構(gòu)造url來(lái)獲取酒店的評(píng)論數(shù)據(jù)了睦尽。

酒店列表頁(yè)網(wǎng)頁(yè)分析

進(jìn)入同程旅行酒店列表網(wǎng)頁(yè)并打開(kāi)開(kāi)發(fā)者工具器净,如下圖所示:


經(jīng)過(guò)查找,發(fā)現(xiàn)酒店基本數(shù)據(jù)(酒店id等)存放在上圖紅框的數(shù)據(jù)包中当凡,其URL鏈接為:

https://www.ly.com/hotelapi/v2/list?pageSize=20&t=1634638146507&city=80&inDate=2021-10-19&outDate=2021-10-20&filterList=8888_1&pageIndex=0&sugActInfo=

觀察URL鏈接山害,可以推測(cè)pageSize每一頁(yè)的酒店數(shù)據(jù)量纠俭,t是時(shí)間戳,city是城市編號(hào)浪慌,inDate冤荆、outDate為入住和離店的時(shí)間,filterList為定值权纤,pageIndex是翻頁(yè)钓简。

好了,網(wǎng)頁(yè)分析就到這里了汹想,接下來(lái)正式開(kāi)始編寫(xiě)代碼來(lái)爬取評(píng)論數(shù)據(jù)外邓。

同步請(qǐng)求獲取酒店id

由于我們請(qǐng)求的酒店列表頁(yè)的URL只要三四個(gè),那么使用同步請(qǐng)求即可古掏,主要代碼如下圖所示:

async def get_link(url):
    response=requests.get(url, headers=headers)
    json = response.json()
    data = json.get('data').get('hotelList')
    hotelName_list = []
    task=[]
    for i in data:
        hotelId = i.get('hotelId')
        hotelName=i.get('hotelName')
        task.append(get_commtent(hotelId,hotelName))
        hotelName_list.append(hotelName)
    await asyncio.wait(task)

首先定義協(xié)程方法get_link()损话,發(fā)送get網(wǎng)絡(luò)請(qǐng)求,返回的數(shù)據(jù)類(lèi)型為json格式槽唾,再通過(guò)get()方法來(lái)獲取酒店名及酒店id丧枪,創(chuàng)建一個(gè)任務(wù)列表task,并將自定義的get_commtent()方法放在task任務(wù)列表中庞萍。

獲取酒店評(píng)論

酒店id拧烦、酒店名已經(jīng)獲取了,接下來(lái)構(gòu)造參數(shù)挂绰,主要代碼如下所示:

#構(gòu)造參數(shù)
data = {
    'keyword': '',
    'objectId': hotelId,
    'pageIndex': i,
    'pageSize': '20',
    'searchFeatures': [],
    'sortingInfo': {
        'sortingDirection': '1',
        'sortingMethod': '0'
    }
}

發(fā)送異步請(qǐng)求屎篱,主要代碼如下圖所示:

async with aiohttp.ClientSession()as session:
    async with session.post(url,json=data,headers=headers)as response:
        Json = await response.json()
        data = Json.get('data').get('comments')
        if data != None:
            for i in data:
                commtent_list = {
                    'hotelName': hotelName,
                    'content': i.get('content').replace(' ', ''),
                    'commentScore': i.get('commentScore'),
                    'createTime': i.get('createTime')
                }
                await saving_data(commtent_list)
        elif data == None:
            commtent_list = {
                'hotelName': hotelName,
                'content': '0',
                'commentScore': '0',
                'createTime': '0'
            }
            await saving_data(commtent_list)

首先通過(guò)async語(yǔ)法來(lái)聲明為異步協(xié)程操作,再通過(guò)post()來(lái)發(fā)送網(wǎng)絡(luò)請(qǐng)求葵蒂,使用await方法來(lái)聲明響應(yīng)內(nèi)容為異步協(xié)程可等待對(duì)象交播,再通過(guò)get()方法來(lái)提取數(shù)據(jù)并把數(shù)據(jù)傳遞到自定義方法saving_data()中。

注意:有些酒店可能是新開(kāi)業(yè)的原因践付,沒(méi)有評(píng)論秦士,所以我們使用if-elif語(yǔ)句來(lái)防止因?yàn)闆](méi)有評(píng)論而報(bào)錯(cuò)。

數(shù)據(jù)保存

數(shù)據(jù)已經(jīng)獲取了永高,接下來(lái)把數(shù)據(jù)保存在MongoDB數(shù)據(jù)庫(kù)中隧土,首先創(chuàng)建MongoDB數(shù)據(jù)庫(kù)和數(shù)據(jù)集合,主要代碼如下所示:

async def create_db(hotelName):
    #連接數(shù)據(jù)庫(kù)
    client = pymongo.MongoClient(host='localhost', port=27017)
    #創(chuàng)造數(shù)據(jù)庫(kù)
    db = client['comment_data']
    #創(chuàng)建數(shù)據(jù)表
    colist=db.list_collection_names()
    for i in hotelName:
        if i not in colist:
            db.create_collection(i)

創(chuàng)建數(shù)據(jù)庫(kù)后命爬,接下來(lái)將保存數(shù)據(jù)曹傀,主要代碼如下圖所示:

async def saving_data(commtent_list):
    #連接數(shù)據(jù)庫(kù)
    client=pymongo.MongoClient(host='localhost',port=27017)
    db=client['comment_data']
    collection=db[commtent_list['hotelName']]
    #插入數(shù)據(jù)到數(shù)據(jù)庫(kù)中
    result=collection.insert_one(commtent_list)

由于代碼比較簡(jiǎn)單,我就直接在代碼里面寫(xiě)注釋饲宛。

最后調(diào)用asyncio.get_event_loop()方法進(jìn)入事件循環(huán)皆愉,再調(diào)用loop.run_until_complete(get_link())方法運(yùn)行事件循環(huán),直到function運(yùn)行結(jié)束。主要代碼如下所示:

for i in range(0,3):
    t=time.time()
    url = f'https://www.ly.com/hotelapi/v2/list?pageSize=20&t={t}&city=80&inDate=2021-10-17&outDate=2021-10-18&filterList=8888_1&pageIndex={i}&sugActInfo='
    loop=asyncio.get_event_loop()
    loop.run_until_complete(get_link(url))

運(yùn)行結(jié)果如下圖所示:

好了幕庐,aiohttp異步協(xié)程爬取同程旅行酒店評(píng)論就講到這里了久锥,感謝觀看!R彀瑟由!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市冤寿,隨后出現(xiàn)的幾起案子歹苦,更是在濱河造成了極大的恐慌,老刑警劉巖疚沐,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暂氯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡亮蛔,警方通過(guò)查閱死者的電腦和手機(jī)痴施,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)究流,“玉大人辣吃,你說(shuō)我怎么就攤上這事》姨剑” “怎么了神得?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)偷仿。 經(jīng)常有香客問(wèn)我哩簿,道長(zhǎng),這世上最難降的妖魔是什么酝静? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任节榜,我火速辦了婚禮,結(jié)果婚禮上别智,老公的妹妹穿的比我還像新娘宗苍。我一直安慰自己,他們只是感情好薄榛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布讳窟。 她就那樣靜靜地躺著,像睡著了一般敞恋。 火紅的嫁衣襯著肌膚如雪丽啡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天硬猫,我揣著相機(jī)與錄音碌上,去河邊找鬼倚评。 笑死浦徊,一個(gè)胖子當(dāng)著我的面吹牛馏予,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盔性,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼霞丧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了冕香?” 一聲冷哼從身側(cè)響起蛹尝,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悉尾,沒(méi)想到半個(gè)月后突那,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡构眯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年愕难,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惫霸。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡猫缭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出壹店,到底是詐尸還是另有隱情猜丹,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布硅卢,位于F島的核電站射窒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏将塑。R本人自食惡果不足惜脉顿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抬旺。 院中可真熱鬧弊予,春花似錦、人聲如沸开财。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)责鳍。三九已至碾褂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間历葛,已是汗流浹背正塌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工嘀略, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乓诽。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓帜羊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鸠天。 傳聞我的和親對(duì)象是個(gè)殘疾皇子讼育,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359