爬蟲

多線程爬蟲

有些時候,比如下載圖片,因為下載圖片是一個耗時的操作。如果采用之前那種同步的方式下載。那效率肯會特別慢。這時候我們就可以考慮使用多線程的方式來下載圖片。

Queue(隊列對象) Queue是python中的標(biāo)準(zhǔn)庫,可以直接import Queue引用;

隊列是線程間最常用的交換數(shù)據(jù)的形式
對于資源,加鎖是個重要的環(huán)節(jié)。因為python原生的list,dict等,都是not thread safe的。而Queue,是線程安全的,因此在滿足使用條件下,建議使用隊列

包中常用的方法
  • Queue.qsize() 返回隊列的大小
  • Queue.empty() 如果隊列為空,返回True,反之False
  • Queue.full() 如果隊列滿了,返回True,反之False
  • Queue.full 與 maxsize 大小對應(yīng)
  • Queue.get([block[, timeout]])獲取隊列,timeout等待時間

迭代器

迭代是訪問集合元素的一種方式。迭代器是一個可以記住遍歷的位置的對象。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結(jié)束。迭代器只能往前不會后退。

可迭代對象 我們已經(jīng)知道可以對list、tuple、str等類型的數(shù)據(jù)使用for...in...的循環(huán)語法從其中依次拿到數(shù)據(jù)進(jìn)行使用,我們把這樣的過程稱為遍歷,也叫迭代

可迭代對象的本質(zhì) 可迭代對象進(jìn)行迭代使用的過程,每迭代一次(即在for...in...中每循環(huán)一次)都會返回對象中的下一條數(shù)據(jù),一直向后讀取數(shù)據(jù)直到迭代了所有數(shù)據(jù)后結(jié)束。

可迭代對象通過iter方法向我們提供一個迭代器,我們在迭代一個可迭代對象的時候,實際上就是先獲取該對象提供的一個迭代器,然后通過這個迭代器來依次獲取對象中的每一個數(shù)據(jù).

  • 一個具備了 iter 方法的對象,就是一個 可迭代對象
iter()函數(shù)與next()函數(shù)

list、tuple等都是可迭代對象,我們可以通過iter()函數(shù)獲取這些可迭代對象的迭代器。然后我們可以對獲取到的迭代器不斷使用next()函數(shù)來獲取下一條數(shù)據(jù)。iter()函數(shù)實際上就是調(diào)用了可迭代對象的iter方法。

  • 迭代器Iterator
    迭代器是用來幫助我們記錄每次迭代訪問到的位置,當(dāng)我們對迭代器使用next()函數(shù)的時候,迭代器會向我們返回它所記錄位置的下一個位置的數(shù)據(jù)。實際上,在使用next()函數(shù)的時候,調(diào)用的就是迭代器對象的next方法。所以,我們要想構(gòu)造一個迭代器,就要實現(xiàn)它的next方法。并且python要求迭代器本身也是可迭代的,所以我們還要為迭代器實現(xiàn)iter方法,迭代器的iter方法返回自身即可。

    一個實現(xiàn)了iter方法和next方法的對象,就是迭代器。

  • for...in...循環(huán)的本質(zhì)
    for item in Iterable 循環(huán)的本質(zhì)就是先通過 iter()函數(shù) 獲取 可迭代對象Iterable的迭代器,然后對獲取到的迭代器不斷調(diào)用 next() 方法來獲取下一個值并將其賦值給item,當(dāng)遇到 StopIteration 的異常后循環(huán)結(jié)束。

生成器
  • 生成器 利用迭代器,我們可以在每次迭代獲取數(shù)據(jù)(通過next()方法)時按照特定的規(guī)律進(jìn)行生成。但是我們在實現(xiàn)一個迭代器時,關(guān)于當(dāng)前迭代到的狀態(tài)需要我們自己記錄,進(jìn)而才能根據(jù)當(dāng)前狀態(tài)生成下一個數(shù)據(jù)。為了達(dá)到記錄當(dāng)前狀態(tài),并配合next()函數(shù)進(jìn)行迭代使用,我們可以采用更簡便的語法,即生成器(generator)。生成器是一類特殊的迭代器。
  • 使用了yield關(guān)鍵字的函數(shù)不再是函數(shù),而是生成器。(使用了yield的函數(shù)就是生成器)
  • yield關(guān)鍵字有兩點作用:
  • 保存當(dāng)前運行狀態(tài)(斷點),然后暫停執(zhí)行,即將生成器(函數(shù))掛起
  • 將yield關(guān)鍵字后面表達(dá)式的值作為返回值返回,此時可以理解為起到了return的作用
  • 可以使用next()函數(shù)讓生成器從斷點處繼續(xù)執(zhí)行.
協(xié)程

協(xié)程,英文叫做 Coroutine,又稱微線程,纖程,協(xié)程是一種用戶態(tài)的輕量級線程。

協(xié)程擁有自己的寄存器上下文和棧。協(xié)程調(diào)度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復(fù)先前保存的寄存器上下文和棧。因此協(xié)程能保留上一次調(diào)用時的狀態(tài),即所有局部狀態(tài)的一個特定組合,每次過程重入時,就相當(dāng)于進(jìn)入上一次調(diào)用的狀態(tài)。

協(xié)程本質(zhì)上是個單進(jìn)程,協(xié)程相對于多進(jìn)程來說,無需線程上下文切換的開銷,無需原子操作鎖定及同步的開銷,編程模型也非常簡單。

我們可以使用協(xié)程來實現(xiàn)異步操作,比如在網(wǎng)絡(luò)爬蟲場景下,我們發(fā)出一個請求之后,需要等待一定的時間才能得到響應(yīng),但其實在這個等待過程中,程序可以干許多其他的事情,等到響應(yīng)得到之后才切換回來繼續(xù)處理,這樣可以充分利用 CPU 和其他資源,這就是異步協(xié)程的優(yōu)勢。

  • 協(xié)程和線程差異
    在實現(xiàn)多任務(wù)時, 線程切換從系統(tǒng)層面遠(yuǎn)不止保存和恢復(fù) CPU上下文這么簡單。 操作系統(tǒng)為了程序運行的高效性每個線程都有自己緩存Cache等等數(shù)據(jù),操作系統(tǒng)還會幫你做這些數(shù)據(jù)的恢復(fù)操作。 所以線程的切換非常耗性能。但是協(xié)程的切換只是單純的操作CPU的上下文,所以一秒鐘切換個上百萬次系統(tǒng)都抗的住
greenlet

為了更好使用協(xié)程來完成多任務(wù),python中的greenlet模塊對其封裝,從而使得切換任務(wù)變的更加簡單

gevent
  • greenlet已經(jīng)實現(xiàn)了協(xié)程,但是這個還的人工切換,是不是覺得太麻煩了,不要捉急,python還有一個比greenlet更強大的并且能夠自動切換任務(wù)的模塊gevent

  • 其原理是當(dāng)一個greenlet遇到IO(指的是input output 輸入輸出,比如網(wǎng)絡(luò)、文件操作等)操作時,比如訪問網(wǎng)絡(luò),就自動切換到其他的greenlet,等到IO操作完成,再在適當(dāng)?shù)臅r候切換回來繼續(xù)執(zhí)行。

  • 由于IO操作非常耗時,經(jīng)常使程序處于等待狀態(tài),有了gevent為我們自動切換協(xié)程,就保證總有g(shù)reenlet在運行,而不是等待IO

  • 進(jìn)程是資源分配的單位

  • 線程是操作系統(tǒng)調(diào)度的單位

  • 進(jìn)程切換需要的資源很最大,效率很低

  • 線程切換需要的資源一般,效率一般(當(dāng)然了在不考慮GIL的情況下)

  • 協(xié)程切換任務(wù)資源很小,效率高

  • 多進(jìn)程、多線程根據(jù)cpu核數(shù)不一樣可能是并行的,但是協(xié)程是在一個線程中所以是并發(fā)的


JavaScript

JavaScript 是網(wǎng)絡(luò)上最常用也是支持者最多的客戶端腳本語言。它可以收集 用戶的跟蹤數(shù)據(jù),不需要重載頁面直接提交表單,在頁面嵌入多媒體文件,甚至運行網(wǎng)頁游戲。
我們可以在網(wǎng)頁源代碼的<scripy>標(biāo)簽里看到,比如:

<script type="text/javascript" src="https://statics.huxiu.com/w/mini/static_2015/js/sea.js?v=201601150944"></script>
jQuery

jQuery 是一個十分常見的庫,70% 最流行的網(wǎng)站(約 200 萬)和約 30% 的其他網(wǎng)站(約 2 億)都在使用。一個網(wǎng)站使用 jQuery 的特征,就是源代碼里包含了 jQuery 入口,比如:

src="https://statics.huxiu.com/w/mini/static_2015/js/jquery-1.11.1.min.js?v=201512181512"></script>
Ajax

我們與網(wǎng)站服務(wù)器通信的唯一方式,就是發(fā)出 HTTP 請求獲取新頁面。如果提交表單之后,或從服務(wù)器獲取信息之后,網(wǎng)站的頁面不需要重新刷新,那么你訪問的網(wǎng)站就在用Ajax 技術(shù)。

Ajax 其實并不是一門語言,而是用來完成網(wǎng)絡(luò)任務(wù)(可以認(rèn)為 它與網(wǎng)絡(luò)數(shù)據(jù)采集差不多)的一系列技術(shù)。Ajax 全稱是 Asynchronous JavaScript and XML(異步 JavaScript 和 XML),網(wǎng)站不需要使用單獨的頁面請求就可以和網(wǎng)絡(luò)服務(wù)器進(jìn)行交互 (收發(fā)信息)。

DHTML

Ajax 一樣,動態(tài) HTML(Dynamic HTML, DHTML)也是一系列用于解決網(wǎng)絡(luò)問題的 技術(shù)集合。DHTML 是用客戶端語言改變頁面的 HTML 元素(HTML、CSS,或者二者皆 被改變)。比如頁面上的按鈕只有當(dāng)用戶移動鼠標(biāo)之后才出現(xiàn),背景色可能每次點擊都會改變,或者用一個 Ajax 請求觸發(fā)頁面加載一段新內(nèi)容,網(wǎng)頁是否屬于DHTML,關(guān)鍵要看有沒有用 JavaScript 控制 HTML 和 CSS 元素。


Selenium

Selenium是一個Web的自動化測試工具,最初是為網(wǎng)站自動化測試而開發(fā)的,類型像我們玩游戲用的按鍵精靈,可以按指定的命令自動操作,不同是Selenium 可以直接運行在瀏覽器上,它支持所有主流的瀏覽器(包括PhantomJS這些無界面的瀏覽器)。 Selenium 可以根據(jù)我們的指令,讓瀏覽器自動加載頁面,獲取需要的數(shù)據(jù),甚至頁面截屏,或者判斷網(wǎng)站上某些動作是否發(fā)生。

Selenium 自己不帶瀏覽器,不支持瀏覽器的功能,它需要與第三方瀏覽器結(jié)合在一起才能使用。但是我們有時候需要讓它內(nèi)嵌在代碼中運行,所以我們可以用一個叫 PhantomJS 的工具代替真實的瀏覽器。

Selenium 庫里有個叫 WebDriver 的 API。WebDriver 有點兒像可以加載網(wǎng)站的瀏覽器,但是它也可以像 BeautifulSoup 或者其他 Selector 對象一樣用來查找頁面元素,與頁面上的元素進(jìn)行交互 (發(fā)送文本、點擊等),以及執(zhí)行其他動作來運行網(wǎng)絡(luò)爬蟲。

注意: 我們使用的有界面瀏覽器,它雖然方便我們觀察,但是在實際運用中是非常消耗性能的 我們也可以使用Chrome的無界面瀏覽器,除了沒有瀏覽器界面以外,其它的相關(guān)操作都與有界面瀏覽器相同

  • 獲取id標(biāo)簽值

element = driver.find_element_by_id("passwd-id")

  • 獲取name標(biāo)簽值

element = driver.find_element_by_name("user-name")

  • 獲取標(biāo)簽名值

element = driver.find_elements_by_tag_name("input")

  • 也可以通過XPath來匹配

element = driver.find_element_by_xpath("http://input[@id='passwd-id']")

Cookies

獲取頁面每個Cookies值,用法如下:

cookies = driver.get_cookies()
for cookie in cookies:
    print("%s -> %s" % (cookie['name'], cookie['value']))

cookie_dict = {i['name']:i['value'] for i in cookies}
print(cookie_dict)
添加cookies

driver.add_cookie(cookie_dict)

刪除Cookies,用法如下
  • 刪除一個特定的cookie
    driver.delete_cookie("CookieName")
  • 刪除所有cookie
    driver.delete_all_cookies()
設(shè)置無頭瀏覽器

opt = webdriver.ChromeOptions()
opt.set_headless()

設(shè)置代理

opt = webdriver.ChromeOptions()
opt.add_argument("--proxy-server=http://118.20.16.82:9999")


數(shù)據(jù)庫基本命令
  • 查看當(dāng)前數(shù)據(jù)庫名稱:db
  • 列出所有在物理上存在的數(shù)據(jù)庫:show dbs
  • 切換數(shù)據(jù)庫 如果數(shù)據(jù)庫不存在,則指向數(shù)據(jù)庫,但不創(chuàng)建,直到插入數(shù)據(jù)或創(chuàng)建集合時數(shù)據(jù)庫才被創(chuàng)建:use 數(shù)據(jù)庫名稱
  • 查看當(dāng)前數(shù)據(jù)庫信息:db.stats()
  • 數(shù)據(jù)庫刪除:刪除當(dāng)前指向的數(shù)據(jù)庫,如果數(shù)據(jù)庫不存在,則什么也不做:db.dropDatabase()
創(chuàng)建集合

:db.createCollection(name, options)

  • 不限制集合大小:db.createCollection("stu")
查看當(dāng)前數(shù)據(jù)庫所有集合
  • show collections:當(dāng)前數(shù)據(jù)庫的集合數(shù)
刪除集合
  • db.集合名稱.drop() 如果成功刪除選定集合,則 drop() 方法返回 true,否則返回 false
數(shù)據(jù)的增、刪、改、基本查詢
插入文檔

語法

db.集合名稱.insert(document)

插入文檔時,如果不指定_id參數(shù),MongoDB會為文檔分配一個唯一的ObjectId

db.stu.insert({name:'張三',gender:1})

多條插入

db.stu.insert([{name:'小明',gender:1},{name:'小紅',gender:0}])

查詢?nèi)课臋n

語法: db.集合名稱.find()

db.stu.find()

更新文檔

全文檔更新

db.stu.update({name:'xxxxx'},{name:'張xxx'})

指定屬性更新,通過操作符$set

db.stu.insert({name:'李四',gender:1}) db.stu.update({name:'李四'},{$set:{name:'李四'}})

save() 方法
save() 方法通過傳入的文檔來替換已有文檔,如果文檔的_id已經(jīng)存在則修改,如果文檔的_id不存在則添加 db.集合名稱.save(document)

db.stu.save({_id:'20180820101010','name':'保存',gender:1})

刪除文檔

  • db.集合名稱.remove(document)
  • 只刪除1條,1表示是否只刪除一條為true的意思 db.集合名稱.remove(document,1) db.集合名稱.remove(document,{justOne:true})
  • 表示刪除全部 db.集合名稱.remove({})

查詢:

db.集合名稱.find({條件文檔})

方法findOne():查詢,只返回第一個

db.集合名稱.findOne({條件文檔})

方法pretty():將結(jié)果格式化

db.集合名稱.find({條件文檔}).pretty()

查詢出姓名等于李某某的學(xué)生

db.stu.find({name:'李某某'})


Limit與Skip方法

limit() 方法 讀取指定數(shù)量的數(shù)據(jù)記錄
基本語法如下所示:

db.COLLECTION_NAME.find().limit(num)

Skip() 方法 使用skip()方法來跳過指定數(shù)量的數(shù)據(jù),skip方法同樣接受一個數(shù)字參數(shù)作為跳過的記錄條數(shù)。
基本語法格式如下:

db.集合名稱.find().skip(num)

limit() 方法、Skip() 方法 同時使用,不分先后順序 表示跳過多少條,返回多少條
查詢第5至8條數(shù)據(jù)

db.stu.find().limit(4).skip(5)

sort() 方法排序

sort() 方法對數(shù)據(jù)進(jìn)行排序,sort() 方法可以通過參數(shù)指定排序的字段,并使用 1 和 -1 來指定排序的方式,其中 1 為升序排列,而 -1 是用于降序排列。

基本語法如下所示:
升序

db.集合名稱.find().sort({要排序的字段:1})

降序

db.集合名稱.find().sort({要排序的字段:-1})

根據(jù)多個字段排序: 例:先根據(jù)年齡做降序,再根據(jù)性別做升序

db.集合名稱.find().sort({age:-1,gender:1})

Scrapy 框架
  • Scrapy是用純Python實現(xiàn)一個為了爬取網(wǎng)站數(shù)據(jù)、提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架,用途非常廣泛。
  • 框架的力量,用戶只需要定制開發(fā)幾個模塊就可以輕松的實現(xiàn)一個爬蟲,用來抓取網(wǎng)頁內(nèi)容以及各種圖片,非常之方便。
  • Scrapy 使用了 Twisted['tw?st?d] 異步網(wǎng)絡(luò)框架來處理網(wǎng)絡(luò)通訊,可以加快我們的下載速度,不用自己去實現(xiàn)異步框架,并且包含了各種中間件接口,可以靈活的完成各種需求。

異步:調(diào)用在發(fā)出之后,這個調(diào)用就直接返回,不管有無結(jié)果 非阻塞:關(guān)注的是程序在等待調(diào)用結(jié)果(消息,返回值)時的狀態(tài),指在不能立刻得到結(jié)果之前,該調(diào)用不會阻塞當(dāng)前線程

  • Scrapy Engine(引擎): 負(fù)責(zé)Spider、ItemPipeline、Downloader、Scheduler中間的通訊,信號、數(shù)據(jù)傳遞等。
  • Scheduler(調(diào)度器): 它負(fù)責(zé)接受引擎發(fā)送過來的Request請求,并按照一定的方式進(jìn)行整理排列,入隊,當(dāng)引擎需要時,交還給引擎。
  • Downloader(下載器):負(fù)責(zé)下載Scrapy Engine(引擎)發(fā)送的所有Requests請求,并將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理,
  • Spider(爬蟲):它負(fù)責(zé)處理所有Responses,從中分析提取數(shù)據(jù),獲取Item字段需要的數(shù)據(jù),并將需要跟進(jìn)的URL提交給引擎,再次進(jìn)入Scheduler(調(diào)度器),
  • Item Pipeline(管道):它負(fù)責(zé)處理Spider中獲取到的Item,并進(jìn)行進(jìn)行后期處理(詳細(xì)分析、過濾、存儲等)的地方.
  • Downloader Middlewares(下載中間件):你可以當(dāng)作是一個可以自定義擴展下載功能的組件。
  • Spider Middlewares(Spider中間件):你可以理解為是一個可以自定擴展和操作引擎和Spider中間通信的功能組件(比如進(jìn)入Spider的Responses;和從Spider出去的Requests)

制作 Scrapy 爬蟲 一共需要4步:

  • 新建項目

scrapy startproject 爬蟲項目名稱

  • 新建一個新的爬蟲

  • 明確目標(biāo)

編寫items.py):明確你想要抓取的目標(biāo)

  • 制作爬蟲

scrapy genspider 爬蟲文件名稱 域名:制作爬蟲開始爬取網(wǎng)頁

  • 存儲內(nèi)容

pipelines.py):設(shè)計管道存儲爬取內(nèi)容

關(guān)于爬蟲部分一些建議:
  • 盡量減少請求次數(shù),能抓列表頁就不抓詳情頁,減輕服務(wù)器壓力,程序員都是混口飯吃不容易。
  • 當(dāng)web網(wǎng)站反爬蟲手段比較嚴(yán)格時,不要只看 Web 網(wǎng)站,還有手機 App 和 H5,這樣的反爬蟲措施一般比較少。
  • 實際應(yīng)用時候,之前一般防守方做到根據(jù) IP 限制頻次就結(jié)束了,除非很核心的數(shù)據(jù),不會再進(jìn)行更多的驗證,畢竟成本的問題會考慮到還要考慮到用戶體驗。
  • 如果真的對性能要求很高,可以考慮多線程、多進(jìn)程(一些成熟的框架如 Scrapy都已支持),甚至分布式...
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 32,001評論 2 89
  • 簡介 MongoDB 是一個基于分布式文件存儲的NoSQL數(shù)據(jù)庫 由C++語言編寫,運行穩(wěn)定,性能高 旨在為 WE...
    大熊_7d48閱讀 37,507評論 1 9
  • 一、收獲的4個知識點 1、組織經(jīng)驗萃取標(biāo)準(zhǔn):可模仿、可復(fù)制、能分解、能應(yīng)用。 這個道理說出來我們都懂,但是實際萃取...
    Ange_7ea4閱讀 7,196評論 0 1
  • iOS事件處理- 用戶使用App產(chǎn)生的事件及響應(yīng)方法: iOS中不是任何對象都能處理事件,只有繼承UIRespon...
    ValienZh閱讀 346評論 0 0
  • 計劃執(zhí)行又放下,然后過一陣子又開始又放下……如此循環(huán),一次次給自己找動力,自己恨自己意志薄弱。 然而作者認(rèn)為,動力...
    Tianjiejie閱讀 114評論 0 0