利用selenium解析及下載資源

1. 緣由

????接到朋友求助,能否幫他將云盤上的資料下載下來承冰;資料都是些文本文檔华弓,按照目錄結(jié)構(gòu)組織,當(dāng)然也希望下載到本地后能夠按照目錄劃分困乒。
在拿到賬號(hào)和密碼后寂屏,我登錄上去,云盤里的內(nèi)容大致如下:


QQ截圖20180630112917.jpg

2. 方案分析

2.1 需要解決問題

????從要求來看娜搂,需要解決的點(diǎn)主要如下:

  • 自動(dòng)登錄:給定賬號(hào)迁霎、密碼、url自動(dòng)登錄百宇。

  • 登陸后去除提示框考廉。當(dāng)時(shí)登錄發(fā)現(xiàn)每次登錄會(huì)出現(xiàn)一個(gè)提示框,需要點(diǎn)擊繼續(xù)使用之后才能繼續(xù)携御。如下:


    QQ截圖20180630131458.jpg
  • 資源地址按照云盤的文件夾組織昌粤,以便后續(xù)下載文件按文件夾放置。

  • 按照云盤結(jié)構(gòu)下載存儲(chǔ)資源啄刹。

2.2 解決方案

(1). 自動(dòng)登錄

????首先要實(shí)現(xiàn)自動(dòng)登錄涮坐,當(dāng)然要祭出selenium神器了,只需要幾行python代碼就可以自動(dòng)登錄誓军。

(2). 資源解析

????由于使用python練習(xí)過爬蟲袱讹,爬過圖片、文檔資源連接昵时,但都是使用request捷雕、urllib等完成的,且目標(biāo)網(wǎng)站資源簡(jiǎn)單债查,地址格式都類似非区,只需簡(jiǎn)單拼接借號(hào)。但這個(gè)云盤資源地址的資源不是直接展示的盹廷,是依賴每次鼠標(biāo)點(diǎn)擊文件夾資源征绸,觸發(fā)js然后get一個(gè)地址,切換到另一個(gè)文件夾資源;對(duì)文檔資源js觸發(fā)get下載操作管怠。所以淆衷,解析資源的操作使用selenium會(huì)方便很多,css_selector渤弛、xpath方式均可祝拯。

(3). 資源下載及存儲(chǔ)

????還有個(gè)問題就是本地存儲(chǔ)目錄結(jié)構(gòu)比照照云盤目錄格結(jié)構(gòu),這個(gè)實(shí)現(xiàn)方案有2種:

  • 先下載所有文件(瀏覽器設(shè)置的默認(rèn)下載位置)她肯,然后依據(jù)解析的“文件夾-資源文件”格式佳头,移動(dòng)響應(yīng)文件到文件夾。
  • 也可以使用selenium不斷更換瀏覽器下載存儲(chǔ)地址晴氨,批次地下載對(duì)應(yīng)文件夾相關(guān)的文件康嘉。但是,每個(gè)文件夾就必須要新開一個(gè)chrome實(shí)例籽前,特別耗費(fèi)資源亭珍,也容易被反爬。

3. 方案實(shí)現(xiàn)

3.1 自動(dòng)登錄

????selenium實(shí)現(xiàn)自動(dòng)登錄非常簡(jiǎn)單枝哄,只需要簡(jiǎn)單分析下網(wǎng)站的登錄框肄梨,模擬人填入相應(yīng)的賬號(hào)密碼、點(diǎn)擊提交按鈕即可挠锥。

    #  實(shí)例化瀏覽器對(duì)象
    browser = webdriver.Chrome()
    # 最大化瀏覽器
    browser.maximize_window()
    #  這里設(shè)置智能等待10s
    browser.implicitly_wait(10)  
    
    #  網(wǎng)址
    browser.get('訪問的網(wǎng)址') #  相當(dāng)于你打開瀏覽器輸入地址众羡、enter
    
    #  用戶名和密碼
    username="用戶名"
    passwd="密碼"
    
    #  找到登錄位置填入用戶信息
    elem=browser.find_element_by_id("userName") # 發(fā)現(xiàn)的該云盤的登錄框中用戶輸入框ID
    elem.send_keys(username) #  填入用戶名
    elem=browser.find_element_by_id("password") # 發(fā)現(xiàn)的該云盤的登錄框中密碼輸入框ID
    elem.send_keys(passwd) #  填入密碼
    elem=browser.find_element_by_id("login-btn") #  找到登錄按鈕id
    elem.click() # 點(diǎn)擊提交

3.2 去掉提示框

????最開始因?yàn)椴皇煜で岸说囊恍〇|西,導(dǎo)致每次登錄都解析不出資源瘪贱,命名分析了頁面元素纱控,但是用盡各種xpath、css_selector選擇器都還是無法解析出相關(guān)html元素菜秦。
????經(jīng)歷過艱難的填坑之后甜害,才發(fā)現(xiàn)可能是iframe的問題。掙扎之后的解決方案:

(1). 關(guān)閉提示框

首先需要解決的是除提示框:我用的比較粗暴的辦法球昨,通過selenium提供的find_element_by_link_text方法尔店,找到繼續(xù)使用網(wǎng)頁版,觸發(fā)點(diǎn)擊完成關(guān)閉提示框主慰。

(2). 切換iframe

????僅僅是關(guān)閉提示框嚣州,仍然無法解析相關(guān)資源,通過分析多個(gè)頁面切換的html元素共螺,發(fā)現(xiàn)僅在首次登錄的時(shí)候會(huì)在默認(rèn)iframe该肴,當(dāng)開始訪問具體資源文件夾時(shí),所有的資源相關(guān)內(nèi)容都在id名為mainFrame的iframe藐不。
????找到問題之后匀哄,解決方案就很簡(jiǎn)單了:自動(dòng)登錄-->關(guān)閉提示框-->切換mainFrame ……代碼如下:

 #  點(diǎn)擊繼續(xù)使用秦效,去掉遮罩層
    browser.find_element_by_link_text(u'繼續(xù)使用網(wǎng)頁版').click()
    
    #  點(diǎn)擊訪問技術(shù)文檔內(nèi)容,目的是簡(jiǎn)單涎嚼,不去解析"技術(shù)文檔"所在地址再點(diǎn)擊
    browser.get('訪問技術(shù)文檔地址')
    
    #  切換到id為mainFrame的iframe上阱州,才能獲取到文件夾列表內(nèi)容
    browser.switch_to.frame("mainFrame")  # 用id來定位

3.3 解析資源

????應(yīng)該說,每個(gè)網(wǎng)站的布局法梯、獲取資源分時(shí)都不同苔货,需要具體問題具體分析。這部分內(nèi)容沒什么共性立哑,唯一的共性就是如何找到你想要的元素夜惭,提取出自己需要的內(nèi)容。
????對(duì)于這個(gè)下載要求來講刁憋,無外乎完成如下功能:

  • 訪問一個(gè)文件夾滥嘴,解析當(dāng)前頁面所有文件夾地址、文檔資源地址
  • 按照文件夾 -- 子文件件/文檔資源組成以文件夾為key至耻,文檔地址或子文件夾地址為value的字典/map結(jié)構(gòu)完成資源地址存儲(chǔ)。
    ????網(wǎng)頁結(jié)構(gòu)分析也不再詳細(xì)說镊叁,對(duì)于該云盤資源尘颓,關(guān)鍵點(diǎn)在于,頁面結(jié)構(gòu)如下:
    html-->body-->...->list(每個(gè)頁面混合子文件夾晦譬、文檔資源)-->th/tr-->input
    其中:
  • tr包含多個(gè)屬性疤苹,其中type屬性指定了資源類型,type是folder則對(duì)應(yīng)文件夾資源敛腌,type是file則對(duì)應(yīng)文件夾資源卧土。
  • tr之下還有多個(gè)input標(biāo)簽,input[1]指示文件夾/資源文件名像樊,input[2]則是對(duì)應(yīng)的folderId或者fileID尤莺。
    fileName_folder_fileUri = []
    browser.get(targetUrl) #  切換到想要解析的資源頁面
    element = browser.find_element_by_id('listContent') # 先定位到id是listContent的元素,如果有id的以id定位最方便快捷準(zhǔn)確
    trElements = element.find_elements_by_tag_name('tr') # 依據(jù)tag為tr找到所有的tr元素
    listuri = []
    for trElement in trElements: #  遍歷每個(gè)tr元素生棍,準(zhǔn)備解析具體的文件夾或者文件資源
        # print trElement
        if trElement.get_attribute('type') == 'folder': #  判斷該tr是文件夾元素
            inputElements = trElement.find_elements_by_tag_name('input') # 解析input元素
            folderName = inputElements[1].get_attribute('value').rstrip() # 解析文件夾名
            folderUrl = baseFolderUrl+inputElements[2].get_attribute('value') # 解析文件夾ID
            listuri.append(folderName+'#'+folderUrl) # 自定義組裝方式颤霎,準(zhǔn)備先存儲(chǔ)到本地
            print "folderName=%s, folderUrl=%s" % (folderName,folderUrl)
        elif trElement.get_attribute('type') == 'file': #  如果是文件資源
            inputElements = trElement.find_elements_by_tag_name('input') # 定位該tr下的所有input元素
            filerName = inputElements[1].get_attribute('value').rstrip() # 解析文件名
            fileUrl = baseFileUrl+inputElements[2].get_attribute('value') # 解析文件地址
            fileName_folder_fileUri.append(filerName+'#'+path+'#'+fileUrl) # 組裝成文件名#文件夾名#文件資源地址

3.4 遞歸解析資源

????由于資源方式是父子文件夾,文件夾嵌套涂滴、且單個(gè)文件夾同時(shí)包含文件夾友酱、文件資源,因此還需能遞歸調(diào)用實(shí)現(xiàn)遍歷所有的資源地址柔纵。代碼如下:

def getResourceRecursively(browser,baseFolderUrl, baseFileUrl, targetUrl, path):
    print u'-----------------遞歸解析資源------------------------------------'
    print "get url: %s ..." % targetUrl
    print "all file are : %s ..." % path
    fileName_folder_fileUri = []
    browser.get(targetUrl)
    element = browser.find_element_by_id('listContent')
    trElements = element.find_elements_by_tag_name('tr')
    listuri = []
    for trElement in trElements:
        # print trElement
        if trElement.get_attribute('type') == 'folder':
            inputElements = trElement.find_elements_by_tag_name('input')
            folderName = inputElements[1].get_attribute('value').rstrip()
            folderUrl = baseFolderUrl+inputElements[2].get_attribute('value')
            listuri.append(folderName+'#'+folderUrl)
            print "folderName=%s, folderUrl=%s" % (folderName,folderUrl)
        elif trElement.get_attribute('type') == 'file':
            inputElements = trElement.find_elements_by_tag_name('input') 
            filerName = inputElements[1].get_attribute('value').rstrip()
            fileUrl = baseFileUrl+inputElements[2].get_attribute('value')
            fileName_folder_fileUri.append(filerName+'#'+path+'#'+fileUrl)
            #  print "filename=%s, fileUrl=%s" % (filerName,fileUrl)
    #  待當(dāng)前頁面所有文件夾uri獲取到之后缔杉,遞歸調(diào)用獲取子目錄資源
    for val in listuri:
        #  遞歸調(diào)用,對(duì)當(dāng)前頁面比如解析到3個(gè)文件夾地址搁料,則3個(gè)文件夾地址都需調(diào)用或详,如果進(jìn)去的文件夾還有文件夾系羞,就繼續(xù)遞歸
        sub_fileName_folder_fileUri = getResourceRecursively(browser,baseFolderUrl, baseFileUrl, val.split('#')[1], os.path.join(path,val.split('#')[0]))
        #print sub_fileName_folder_fileUri
        fileName_folder_fileUri.extend(sub_fileName_folder_fileUri)
    print u'-----------------end------------------------------------'
    #  如果當(dāng)前頁面所有文件夾資源遍歷完畢,或者只有文件資源鸭叙,遞歸結(jié)束條件結(jié)束觉啊,返回解析到文件資源
    return fileName_folder_fileUri

????

參數(shù)說明:

  • baseFolderUrl:文件夾資源基本串,該網(wǎng)站使用的基本串+folderID(我們解析出來的)方式
  • baseFileUrl:同理沈贝,只是文件資源基本串+fileId
  • targetUrl:每次遞歸需要解析的頁面地址

解析過程大致如下杠人,類似深度優(yōu)先遍歷的過程,先對(duì)一個(gè)目錄遍歷到底宋下,再逐個(gè)從底層返回:


QQ截圖20180630131228.jpg

4.下載資源

????之前說到嗡善,下載方式要么一堆解析到的資源一次性下載,然后按照自己組裝解析文件夾 -- 子文件夾/文件資源對(duì)應(yīng)關(guān)系学歧,使用python的os模塊完成文件挪動(dòng)罩引,之前的想法是將這種文件夾層級(jí)關(guān)系組裝為json格式,方便處理枝笨。


QQ截圖20180630133605.jpg

????但是實(shí)際操作會(huì)發(fā)現(xiàn)袁铐,瀏覽器下載文件時(shí),對(duì)于中文文件名空格等總會(huì)加上些亂七八糟的字符横浑,如:


QQ截圖20180630132203.jpg

這對(duì)于文件名匹配可不是好事剔桨,解析時(shí)都是正常的文件名,下載后的這種必然匹配不上徙融,因此放棄洒缀。
另外,考慮到一次下載完資源欺冀,如果中途出現(xiàn)失敗也比較麻煩树绩,如圖:


QQ截圖20180630132906.jpg

????轉(zhuǎn)而采用配置chrome默認(rèn)下載目錄的方式,不過考慮到文件資源眾多隐轩,文件夾數(shù)量眾多饺饭,而且想使用selenium配置chrome下載目錄,必須每次配置都新啟動(dòng)一個(gè)實(shí)例才會(huì)生效龙助。
????考慮到上述情況砰奕,解決方案如下:

  • 將資源切分多個(gè)子文件,逐個(gè)子文件下載
  • 采用配置瀏覽器下載目錄方式提鸟,每隔新配置的實(shí)例只下載一個(gè)目錄下的所有文件資源連接军援。當(dāng)然,配置下載目錄前會(huì)先創(chuàng)建對(duì)應(yīng)目錄称勋。


    QQ截圖20180630133953.jpg
#  先解析資源文件胸哥,得到所有資源list
with open('fileUri1_1301_1375.txt') as f: 
    records =  f.readlines()
    #uris = [x.split('#')[2] for x in f.readlines()]
    fileuris = [x.split('#')[2].decode('utf-8') for x in records]
    folders = [x.split('#')[1].decode('utf-8') for x in records]
    #  將資源地址解析封裝成資源連接為key,應(yīng)該存儲(chǔ)的文件夾為value的dict赡鲜,所有資源組成list返回
    uris = list(map(lambda x, y : [x, y], fileuris, folders))
#  資源總數(shù)
uri_count = len(uris)   
print u'總計(jì)解析到%d個(gè)資源鏈接空厌。' % uri_count

#  組成文件夾--文件資源list的dict結(jié)構(gòu)
folder_fileuri = {}
#  初始化字典庐船,key為文件夾名
for folder in folders:
    folder_fileuri[folder] = []
print u'初始化完成!總計(jì)文件夾個(gè)數(shù):%d' % len(folder_fileuri)

#  在將list解析為文件夾為key嘲更,對(duì)應(yīng)的文件資源地址list鏈接為value組成的dict筐钟,轉(zhuǎn)為json是為了方便寫入文件
for uri in uris:
    folder_fileuri[uri[1]].append(uri[0])
jsondata = json.dumps(folder_fileuri, encoding="UTF-8", ensure_ascii=False, sort_keys=False, indent=4)


下載資源實(shí)現(xiàn):配置下載目錄,逐個(gè)資源get請(qǐng)求即可

def downloadFileList(fileList, downLoadPath):
    #  聲明瀏覽器對(duì)象赋朦,配置下載默認(rèn)下載地址參數(shù)
    options = webdriver.ChromeOptions() 
    prefs = {'profile.default_content_settings.popups': 0, 'download.default_directory': downLoadPath}
    options.add_experimental_option('prefs', prefs)
    browser = webdriver.Chrome(chrome_options=options)
    # 最大化瀏覽器
    #browser.maximize_window()
    #  這里設(shè)置智能等待10s
    browser.implicitly_wait(10)  
    
    #  網(wǎng)址
    browser.get('首頁地址')
    
    #  用戶名和密碼
    username="用戶名"
    passwd="密碼"
    
    #  找到登錄位置填入用戶信息
    elem=browser.find_element_by_id("userName")
    elem.send_keys(username)
    elem=browser.find_element_by_id("password")
    elem.send_keys(passwd)
    elem=browser.find_element_by_id("login-btn")
    elem.click()
    
    #  點(diǎn)擊繼續(xù)使用篓冲,去掉遮罩層
    browser.find_element_by_link_text(u'繼續(xù)使用網(wǎng)頁版').click()
    
    #  點(diǎn)擊訪問技術(shù)文檔內(nèi)容
    browser.get('訪問技術(shù)文檔地址')
    
    #  切換到id為mainFrame的iframe上,才能獲取到文件夾列表內(nèi)容
    browser.switch_to.frame("mainFrame")  # 用id來定位
    #  逐個(gè)下載
    for fileuri in fileList:
        print u'下載%s到目錄:%s ...' % (fileuri, downLoadPath)
        browser.get(fileuri)

創(chuàng)建文件夾邏輯:

## 
#  @Brief 創(chuàng)建目錄
#  
#  @Param 待創(chuàng)建目錄
#  @return 無返回
#  
#  @Details 測(cè)試目錄存在與否宠哄,無則創(chuàng)建目錄
#  
def createDirIfNull(dir):
    if(not os.path.exists(dir.strip())):
        print u'目錄%s不存在壹将,現(xiàn)在創(chuàng)建...' % dir

調(diào)用下載的主邏輯:

#  遍歷下載,下載到不同文件夾
folder_coumt = 1
for folder in folder_fileuri: #  folder_fileuri就是每次讀取資源文件解析成的文件夾為key毛嫉,對(duì)應(yīng)文件夾下文件資源鏈接list為value的dict
    print u'開始下載%s文件夾對(duì)應(yīng)的資源...' % folder
    createDirIfNull(folder)
    downloadFileList(folder_fileuri[folder], folder)
    if(folder_coumt%2 == 0):
        print u'還有%s個(gè)文件夾所屬資源需要下載, 暫停5s...' % (str(len(folder_fileuri)-folder_coumt))
        time.sleep(2)
    folder_coumt = folder_coumt + 1

time.sleep(15)
#  下載完成
print u'所有文件下載完畢诽俯!'

下載后的成果:


QQ截圖20180630140215.jpg

5.總結(jié)

????雖然實(shí)現(xiàn)了下載功能,但是仍然有幾個(gè)問題:

(1). 反爬問題:

好在下載過程中并未出現(xiàn)承粤,其實(shí)應(yīng)該配合代理IP地址暴区,每次訪問通過代理IP請(qǐng)求下載,能夠避免很多問題辛臊。

(2). 代碼結(jié)構(gòu):

主邏輯部分較為混亂颜启,也沒花心思擺弄,改為類實(shí)現(xiàn)應(yīng)該能省去很多參數(shù)傳遞問題浪讳。

(3). chromedriver

selenium需要chromedriver,這是個(gè)可執(zhí)行文件涌萤,下載下來放到python安裝目錄或者當(dāng)前項(xiàng)目目錄即可淹遵,只有python能找到。至于如何匹配自己的chrome版本负溪,可以參考地址:https://www.cnblogs.com/xqtesting/p/8334997.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末透揣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子川抡,更是在濱河造成了極大的恐慌辐真,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崖堤,死亡現(xiàn)場(chǎng)離奇詭異侍咱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)密幔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門楔脯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人胯甩,你說我怎么就攤上這事昧廷】吧” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵木柬,是天一觀的道長(zhǎng)皆串。 經(jīng)常有香客問我,道長(zhǎng)眉枕,這世上最難降的妖魔是什么恶复? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮齐遵,結(jié)果婚禮上寂玲,老公的妹妹穿的比我還像新娘。我一直安慰自己梗摇,他們只是感情好拓哟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伶授,像睡著了一般断序。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上糜烹,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天违诗,我揣著相機(jī)與錄音,去河邊找鬼疮蹦。 笑死诸迟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的愕乎。 我是一名探鬼主播阵苇,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼感论!你這毒婦竟也來了绅项?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤比肄,失蹤者是張志新(化名)和其女友劉穎快耿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芳绩,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掀亥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了示括。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铺浇。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垛膝,靈堂內(nèi)的尸體忽然破棺而出鳍侣,到底是詐尸還是另有隱情丁稀,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布倚聚,位于F島的核電站线衫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惑折。R本人自食惡果不足惜授账,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惨驶。 院中可真熱鬧白热,春花似錦、人聲如沸粗卜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽续扔。三九已至攻臀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纱昧,已是汗流浹背刨啸。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留识脆,地道東北人设联。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像灼捂,于是被迫代替她去往敵國(guó)和親仑荐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,749評(píng)論 25 707
  • 1纵东、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,969評(píng)論 3 119
  • 月沒西山, 晨光熹微啥寇。 宿鳥攜風(fēng)振翅偎球, 池面樹影微疊。 雖清波渺渺辑甜, 無有千尺深衰絮, 不似桃花潭。 命里相遇都成客磷醋,...
    惡竹閱讀 149評(píng)論 0 1
  • 有的人可以打麻將三天三夜猫牡,有的人可以打電玩三天三夜,有的人可以讀書三天三夜……都辛苦邓线,都不辛苦淌友,樂在其中煌恢,自然會(huì)廢...
    大胡子逸舟閱讀 485評(píng)論 0 1
  • 規(guī)律 你的成(發(fā))長(zhǎng)(展),終究還是要經(jīng)過生根震庭,發(fā)芽瑰抵,生長(zhǎng),綻放器联。自然的規(guī)律二汛,哪怕你是萬年的常青...
    夏雨凡星閱讀 161評(píng)論 0 0