<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專(zhuān)題視頻專(zhuān)題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專(zhuān)題1關(guān)鍵字專(zhuān)題50關(guān)鍵字專(zhuān)題500關(guān)鍵字專(zhuān)題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專(zhuān)題關(guān)鍵字專(zhuān)題tag2tag3文章專(zhuān)題文章專(zhuān)題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專(zhuān)題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        python實(shí)現(xiàn)douban.fm簡(jiǎn)易客戶(hù)端

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 14:17:26
        文檔

        python實(shí)現(xiàn)douban.fm簡(jiǎn)易客戶(hù)端

        python實(shí)現(xiàn)douban.fm簡(jiǎn)易客戶(hù)端:一個(gè)月前心血來(lái)潮用python實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的douban.fm客戶(hù)端,計(jì)劃是陸續(xù)將其完善成為Ubuntu下可替代web版本的douban.fm客戶(hù)端。但后來(lái)因?yàn)槭露啵灰恢睌R著,沒(méi)有再繼續(xù)完善。就在昨天,一位園友在評(píng)論中提到了登錄的實(shí)現(xiàn),雖然最近依然事多,但突然很想實(shí)現(xiàn)
        推薦度:
        導(dǎo)讀python實(shí)現(xiàn)douban.fm簡(jiǎn)易客戶(hù)端:一個(gè)月前心血來(lái)潮用python實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的douban.fm客戶(hù)端,計(jì)劃是陸續(xù)將其完善成為Ubuntu下可替代web版本的douban.fm客戶(hù)端。但后來(lái)因?yàn)槭露啵灰恢睌R著,沒(méi)有再繼續(xù)完善。就在昨天,一位園友在評(píng)論中提到了登錄的實(shí)現(xiàn),雖然最近依然事多,但突然很想實(shí)現(xiàn)
        一個(gè)月前心血來(lái)潮用python實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的douban.fm客戶(hù)端,計(jì)劃是陸續(xù)將其完善成為Ubuntu下可替代web版本的douban.fm客戶(hù)端。但后來(lái)因?yàn)槭露啵灰恢睌R著,沒(méi)有再繼續(xù)完善。就在昨天,一位園友在評(píng)論中提到了登錄的實(shí)現(xiàn),雖然最近依然事多,但突然很想實(shí)現(xiàn)這個(gè)功能。正好,前幾天因?yàn)橐恍┬枰胮ython實(shí)現(xiàn)過(guò)網(wǎng)站登錄,約摸估計(jì)這douban.fm的登錄不會(huì)差太多。

        關(guān)于網(wǎng)站身份驗(yàn)證

        http協(xié)議被設(shè)計(jì)為無(wú)連接協(xié)議,但現(xiàn)實(shí)中,很多網(wǎng)站需要對(duì)用戶(hù)進(jìn)行身份識(shí)別,cookie就是為此而誕生的。當(dāng)我們用瀏覽器瀏覽網(wǎng)站時(shí),瀏覽器會(huì)幫我們透明的處理cookie。而我們現(xiàn)在要第三方登錄網(wǎng)站,這就必須對(duì)cookie的工作流程有一定的了解。

        另外,很多網(wǎng)站為了防止程序自動(dòng)登錄而使用了驗(yàn)證碼機(jī)制,驗(yàn)證碼的介入會(huì)使登錄過(guò)程變得麻煩,但也還不算太難處理。

        實(shí)際中douban.fm的登錄流程

        為了模擬一個(gè)干凈(不使用已有cookie)的登錄流程,我使用chromium的隱身模式。

        1.jpg

        觀察請(qǐng)求和響應(yīng)頭,可以看到,第一次請(qǐng)求的請(qǐng)求頭是沒(méi)有Cookie字段的,而服務(wù)器的響應(yīng)頭中包含著Set-Cookie字段,這告訴瀏覽器下次請(qǐng)求該網(wǎng)站時(shí)需要攜帶Cookie。

        這里我注意到了一個(gè)有意思的現(xiàn)象,訪問(wèn)douban.fm,實(shí)際中經(jīng)過(guò)了3次重定向。當(dāng)然,一般來(lái)說(shuō)我們并不需要關(guān)注這些細(xì)節(jié),瀏覽器和高級(jí)的httplib會(huì)透明的處理重定向,但如果使用底層的C Socket,就必須小心的處理這些重定向。

        點(diǎn)擊登錄按鈕,瀏覽器發(fā)起幾個(gè)新的請(qǐng)求,其中有幾個(gè)至關(guān)重要的請(qǐng)求,這幾個(gè)請(qǐng)求是我們第三方登錄douban.fm的關(guān)鍵所在。

        首先,有一條請(qǐng)求的URL是http://douban.fm/j/new_captcha,請(qǐng)求該URL,服務(wù)器會(huì)返回一個(gè)隨機(jī)字符串,這有什么用呢?(其實(shí)是個(gè)驗(yàn)證碼)

        再看下一條請(qǐng)求,http://douban.fm/misc/captcha?size=m&id=0iPlm837LsnSsJTMJrf5TZ7e,這條請(qǐng)求會(huì)返回驗(yàn)證碼。原來(lái)如此,請(qǐng)求http://douban.fm/j/new_captcha,將服務(wù)器返回的字符串作為下一條請(qǐng)求的id參數(shù)值。

        我們可以寫(xiě)一段python代碼來(lái)驗(yàn)證我們的想法。

        值得注意的是python提供了3個(gè)http庫(kù),httplib、urllib和urllib2,能透明處理cookie的是urllib2,想我之前用httplib手動(dòng)處理cookie,那個(gè)痛苦啊。

        代碼如下:

        opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(CookieJar()))
        captcha_id = opener.open(urllib2.Request('http://douban.fm/j/new_captcha')).read().strip('"')
        captcha = opener.open(urllib2.Request('http://douban.fm/misc/captcha?size=m&id=' + captcha_id)).read())
        file = open('captcha.jpg', 'wb')
        file = write(captcha)
        file.close()

        這段代碼實(shí)現(xiàn)了驗(yàn)證碼的下載。

        接著,我們填寫(xiě)表單,并提交。

        可以看到,登錄表單的目標(biāo)地址為http://douban.fm/j/login,參數(shù)有:

        source: radio

        alias: 用戶(hù)名

        form_password: 密碼

        captcha_solution: 驗(yàn)證碼

        captcha_id: 驗(yàn)證碼ID

        task: sync_channel_list

        接下來(lái)要做的是用python構(gòu)造一個(gè)表單。

        opener.open(
         urllib2.Request('http://douban.fm/j/login'),
         urllib.urlencode({
         'source': 'radio',
         'alias': username,
         'form_password': password,
         'captcha_solution': captcha,
         'captcha_id': captcha_id,
         'task': 'sync_channel_list'}))

        服務(wù)器返回的數(shù)據(jù)格式是json,具體格式這里不贅訴了,大家可以自己測(cè)試。

        我們?cè)趺粗赖卿浭欠衿鹱饔昧四兀渴橇耍暗奈恼绿岬竭^(guò)channel=-3為紅心兆赫,是用戶(hù)的收藏列表,沒(méi)有登錄是獲取不到該頻道的播放列表的。請(qǐng)求http://douban.fm/j/mine/playlist?type=n&channel=-3,如果返回你自己收藏過(guò)的音樂(lè)列表,那么就說(shuō)明登錄起作用了。

        代碼整理

        結(jié)合之前的版本和新增的登錄功能,再加上命令行參數(shù)處理、頻道選擇,一個(gè)稍稍完善的douban.fm就完成的

        View Code
         #!/usr/bin/python
         # coding: utf-8
         
         import sys
         import os
         import subprocess
         import getopt
         import time
         import json
         import urllib
         import urllib2
         import getpass
         import ConfigParser
         from cookielib import CookieJar
         
         # 保存到文件
         def save(filename, content):
         file = open(filename, 'wb')
         file.write(content)
         file.close()
         
         
         # 獲取播放列表
         def getPlayList(channel='0', opener=None):
         url = 'http://douban.fm/j/mine/playlist?type=n&channel=' + channel
         if opener == None:
         return json.loads(urllib.urlopen(url).read())
         else:
         return json.loads(opener.open(urllib2.Request(url)).read())
         
         
         # 發(fā)送桌面通知
         def notifySend(picture, title, content):
         subprocess.call([
         'notify-send',
         '-i',
         os.getcwd() + '/' + picture,
         title,
         content])
         
         
         # 登錄douban.fm
         def login(username, password):
         opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(CookieJar()))
         while True:
         print '正在獲取驗(yàn)證碼……'
         captcha_id = opener.open(urllib2.Request(
         'http://douban.fm/j/new_captcha')).read().strip('"')
         save(
         '驗(yàn)證碼.jpg',
         opener.open(urllib2.Request(
         'http://douban.fm/misc/captcha?size=m&id=' + captcha_id
         )).read())
         captcha = raw_input('驗(yàn)證碼: ')
         print '正在登錄……'
         response = json.loads(opener.open(
         urllib2.Request('http://douban.fm/j/login'),
         urllib.urlencode({
         'source': 'radio',
         'alias': username,
         'form_password': password,
         'captcha_solution': captcha,
         'captcha_id': captcha_id,
         'task': 'sync_channel_list'})).read())
         if 'err_msg' in response.keys():
         print response['err_msg']
         else:
         print '登錄成功'
         return opener
         
         
         # 播放douban.fm
         def play(channel='0', opener=None):
         while True:
         if opener == None:
         playlist = getPlayList(channel)
         else:
         playlist = getPlayList(channel, opener)
         
         if playlist['song'] == []:
         print '獲取播放列表失敗'
         break
         picture,
         
         for song in playlist['song']:
         picture = 'picture/' + song['picture'].split('/')[-1]
         
         # 下載專(zhuān)輯封面
         save(
         picture,
         urllib.urlopen(song['picture']).read())
         
         # 發(fā)送桌面通知
         notifySend(
         picture,
         song['title'],
         song['artist'] + '
        ' + song['albumtitle'])
         
         # 播放
         player = subprocess.Popen(['mplayer', song['url']])
         time.sleep(song['length'])
         player.kill()
         
         
         def main(argv):
         # 默認(rèn)參數(shù)
         channel = '0'
         user = ''
         password = ''
         
         # 獲取、解析命令行參數(shù)
         try: 
         opts, args = getopt.getopt(
         argv, 'u:p:c:', ['user=', 'password=', 'channel=']) 
         except getopt.GetoptError as error:
         print str(error)
         sys.exit(1)
         
         # 命令行參數(shù)處理
         for opt, arg in opts:
         if opt in ('-u', '--user='):
         user = arg
         elif opt in ('-p', '--password='):
         password = arg
         elif opt in ('-c', '--channel='):
         channel = arg
         
         if user == '':
         play(channel)
         else:
         if password == '':
         password = getpass.getpass('密碼:')
         opener = login(user, password)
         play(channel, opener)
         
         
         if __name__ == '__main__':
         main(sys.argv[1:])

        1.png

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        python實(shí)現(xiàn)douban.fm簡(jiǎn)易客戶(hù)端

        python實(shí)現(xiàn)douban.fm簡(jiǎn)易客戶(hù)端:一個(gè)月前心血來(lái)潮用python實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的douban.fm客戶(hù)端,計(jì)劃是陸續(xù)將其完善成為Ubuntu下可替代web版本的douban.fm客戶(hù)端。但后來(lái)因?yàn)槭露啵灰恢睌R著,沒(méi)有再繼續(xù)完善。就在昨天,一位園友在評(píng)論中提到了登錄的實(shí)現(xiàn),雖然最近依然事多,但突然很想實(shí)現(xiàn)
        推薦度:
        • 熱門(mén)焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門(mén)推薦

        專(zhuān)題
        Top
        主站蜘蛛池模板: 日本高清免费观看| a视频在线观看免费| 妞干网免费视频在线观看| 亚洲精品无码久久毛片波多野吉衣 | 成在线人视频免费视频 | 九一在线完整视频免费观看| 蜜桃精品免费久久久久影院| 亚洲精品二三区伊人久久| 无码国产精品一区二区免费式影视| 久久亚洲日韩看片无码| 波多野结衣中文字幕免费视频| 亚洲乱码卡三乱码新区| 97人伦色伦成人免费视频| 在线观看日本亚洲一区| 插B内射18免费视频| 九九精品国产亚洲AV日韩| 亚洲毛片av日韩av无码| 青青操视频在线免费观看| 中文字幕亚洲综合久久| 免费做爰猛烈吃奶摸视频在线观看 | 在线毛片片免费观看| 亚洲黄色在线观看网站| 24小时免费直播在线观看| 国产精品久久久久久亚洲小说 | 中文字幕日本人妻久久久免费| 亚洲精品人成在线观看| 和日本免费不卡在线v| 国产综合成人亚洲区| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 免费看男人j放进女人j免费看| 亚洲精品永久www忘忧草| 日本黄色免费观看| 一级毛片免费观看不收费| 亚洲AV乱码一区二区三区林ゆな| www.免费在线观看| 久久亚洲精品高潮综合色a片| 中文字幕在亚洲第一在线| 1000部拍拍拍18勿入免费视频软件| 亚洲黄页网在线观看| 亚洲香蕉网久久综合影视| 久久久久久国产精品免费无码|