整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          手把手教你使用Python網(wǎng)絡(luò)爬蟲獲取B站視頻選集內(nèi)容(附源碼)

          家好,我是Python進(jìn)階者。

          前言

          前幾天雪球兄在Python交流群里分享了一個(gè)獲取B站視頻選集的Python代碼,小編覺得非常奈斯,這里整理成一篇小文章,分享給大家學(xué)習(xí)。

          關(guān)于雪球兄,大家應(yīng)該都熟悉了,之前他寫過(guò)Python實(shí)戰(zhàn)文章,好評(píng)如潮,沒來(lái)得及看的小伙伴,可以戳這里了:

          盤點(diǎn)常用驗(yàn)證碼標(biāo)注和識(shí)別項(xiàng)目線上部署三種方式——VUE前端、Java后端和Python后端部署

          Python項(xiàng)目實(shí)戰(zhàn)篇——常用驗(yàn)證碼標(biāo)注&識(shí)別(CNN神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練/測(cè)試/部署)

          Python項(xiàng)目實(shí)戰(zhàn)篇——常用驗(yàn)證碼標(biāo)注&識(shí)別(前端+后端實(shí)現(xiàn)高效率數(shù)據(jù)標(biāo)注)

          Python項(xiàng)目實(shí)戰(zhàn)篇——常用驗(yàn)證碼標(biāo)注&識(shí)別(數(shù)據(jù)采集/預(yù)處理/字符圖切割)

          Python項(xiàng)目實(shí)戰(zhàn)篇——常用驗(yàn)證碼標(biāo)注和識(shí)別(需求分析和實(shí)現(xiàn)思路)

          之前也有給大家分享B站的一些文章,感興趣的話可以看看這個(gè)文章,Python網(wǎng)絡(luò)爬蟲+數(shù)據(jù)分析:手把手教你用Python網(wǎng)絡(luò)爬蟲獲取B站UP主10萬(wàn)條數(shù)據(jù)并用Pandas庫(kù)進(jìn)行趣味數(shù)據(jù)分析。


          一、背景引入

          一提到B站,第一印象就是視頻,相信很多小伙伴和我一樣,都想著去利用網(wǎng)絡(luò)爬蟲技術(shù)獲取B站的視頻吧,但是B站視頻其實(shí)沒有那么好拿到的,關(guān)于B站的視頻獲取,之前有介紹通過(guò)you-get庫(kù)進(jìn)行實(shí)現(xiàn),感興趣的小伙伴可以看這篇文章:You-Get 就是這么強(qiáng)勢(shì)!。

          言歸正傳,經(jīng)常在B站上學(xué)習(xí)的小伙伴們可能經(jīng)常會(huì)遇到有的博主連載幾十個(gè),甚至幾百個(gè)視頻,尤其像這種編程語(yǔ)言、課程、工具使用等連續(xù)的教程,就會(huì)出現(xiàn)選集系列,如下圖所示。

          當(dāng)然這些選集的字段我們?nèi)庋垡彩强梢钥吹玫降摹V皇峭ㄟ^(guò)程序來(lái)實(shí)現(xiàn)的話,可能真沒有想象的那么簡(jiǎn)單。那么這篇文章的目標(biāo)呢,就是通過(guò)Python網(wǎng)絡(luò)爬蟲技術(shù),基于selenium庫(kù),實(shí)現(xiàn)視頻選集的獲取。


          二、具體實(shí)現(xiàn)

          這篇文章我們用的庫(kù)是selenium,這個(gè)是一個(gè)用于模擬用戶登錄的庫(kù),雖然給人的感覺是慢,但是在網(wǎng)絡(luò)爬蟲領(lǐng)域,這個(gè)庫(kù)還是用的蠻多的,用它來(lái)模擬登錄、獲取數(shù)據(jù)屢試不爽。下面是實(shí)現(xiàn)視頻選集采集的所有代碼,歡迎大家親自動(dòng)手實(shí)踐。

          # coding: utf-8
          from selenium import webdriver
          from selenium.webdriver.common.by import By
          from selenium.webdriver.support import expected_conditions as EC
          from selenium.webdriver.support.wait import WebDriverWait
          
          
          class Item:
              page_num = ""
              part = ""
              duration = ""
          
          
              def __init__(self, page_num, part, duration):
                  self.page_num = page_num
                  self.part = part
                  self.duration = duration
          
          
              def get_second(self):
                  str_list = self.duration.split(":")
                  sum = 0
                  for i, item in enumerate(str_list):
                      sum += pow(60, len(str_list) - i - 1) * int(item)
          
          
                  return sum
          
          
          def get_bilili_page_items(url):
              options = webdriver.ChromeOptions()
              options.add_argument('--headless')  # 設(shè)置無(wú)界面
              options.add_experimental_option('excludeSwitches', ['enable-automation'])
              # options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2,
              #                                           "profile.managed_default_content_settings.flash": 0})
          
          
              browser = webdriver.Chrome(options=options)
              # browser = webdriver.PhantomJS()
              print("正在打開網(wǎng)頁(yè)...")
              browser.get(url)
          
          
              print("等待網(wǎng)頁(yè)響應(yīng)...")
              # 需要等一下,直到頁(yè)面加載完成
              wait = WebDriverWait(browser, 10)
              wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@class="list-box"]/li/a')))
          
          
              print("正在獲取網(wǎng)頁(yè)數(shù)據(jù)...")
              list = browser.find_elements_by_xpath('//*[@class="list-box"]/li')
              # print(list)
              itemList = []
          
          
              second_sum = 0
          
          
              # 2.循環(huán)遍歷出每一條搜索結(jié)果的標(biāo)題
              for t in list:
                  # print("t text:",t.text)
                  element = t.find_element_by_tag_name('a')
                  # print("a text:",element.text)
                  arr = element.text.split('\n')
                  print(" ".join(arr))
                  item = Item(arr[0], arr[1], arr[2])
                  second_sum += item.get_second()
                  itemList.append(item)
          
          
              print("總數(shù)量:", len(itemList))
              # browser.page_source
          
          
              print("總時(shí)長(zhǎng)/分鐘:", round(second_sum / 60, 2))
              print("總時(shí)長(zhǎng)/小時(shí):", round(second_sum / 3600.0, 2))
          
          
              browser.close()
          
          
              return itemList
          
          
          
          
          get_bilili_page_items("https://www.bilibili.com/video/BV1Eb411u7Fw")

          這里用到的選擇器是xpath,利用視頻示例是B站的《高等數(shù)學(xué)》同濟(jì)版 全程教學(xué)視頻(宋浩老師)視頻選集,大家如果想抓取其他視頻選集的話,只需要更改上述代碼的最后一行的URL鏈接即可。


          三、常見問(wèn)題

          在運(yùn)行過(guò)程中小伙伴們應(yīng)該會(huì)經(jīng)常遇到這個(gè)問(wèn)題,如下圖所示。

          這個(gè)是因?yàn)楣雀栩?qū)動(dòng)版本問(wèn)題導(dǎo)致的,只需要根據(jù)提示,去下載對(duì)應(yīng)的驅(qū)動(dòng)版本即可,驅(qū)動(dòng)下載鏈接:

          https://chromedriver.storage.googleapis.com/index.html


          四、總結(jié)

          我是Python進(jìn)階者。這篇文章主要給大家介紹了B站視頻選集內(nèi)容的獲取方法,基于網(wǎng)絡(luò)爬蟲,通過(guò)selenium庫(kù)和xpath選擇器進(jìn)行實(shí)現(xiàn),并且給大家例舉了常見問(wèn)題的處理方法。小伙伴們,快快用實(shí)踐一下吧!如果在學(xué)習(xí)過(guò)程中,有遇到任何問(wèn)題,歡迎加我好友,我拉你進(jìn)Python學(xué)習(xí)交流群共同探討學(xué)習(xí)。

          不久看到一篇關(guān)于BibiBili視頻地址解析的源碼,正好有興趣,就自己也研究了研究,記錄一下。

          1.以http://www.bilibili.com/video/av12535537/ 此視頻為例用HttpWatch抓包,很容易就能看出視頻的地址是從https://interface.bilibili.com/playurl?quality=4&player=1&cid=20627240&ts=1504780011&sign=f37df88434579a4b009a2bee708a2a71&qn=112里獲取的

          按照常例分析下參數(shù):

          cid很容易猜測(cè)出是視頻的ID號(hào),在網(wǎng)頁(yè)源碼里面也能找到

          ?

          Quality和qn是視頻的清晰度

          ts則是時(shí)間戳,這個(gè)也不用多說(shuō)

          關(guān)鍵就是這個(gè)sign,在HttpWatch中是完全搜不到任何相關(guān)的信息的,但網(wǎng)頁(yè)訪問(wèn)了http://static.hdslb.com/play.swf這個(gè)文件,那么sign算法很可能就在這個(gè)播放器里。

          2.下載這個(gè)SWF文件后,載入AS3 Sorcerer,代碼一大片不是很好找

          ?

          那就保存到文本里,在文本中查找”視頻地址”這個(gè)關(guān)鍵字。

          ?

          很快就能定位到關(guān)鍵的函數(shù)LoadPreview和LoadCidVideo那么接著搜索LoadPreview和LoadCidVideo定位到函數(shù)部分,可以看到代碼如下

          ?

          那么關(guān)鍵算法就是在getSign和getSign_v2里面了

          [mw_shl_code=actionscript3,true]public function getSign(_arg_1:String):String

          {

          var _local_2:int;

          var _local_4 = null;

          var _local_7:int;

          var _local_8:int;

          var _local_6:int;

          var _local_5:int;

          var _local_3:int = ESP;

          _local_2 = _local_3;

          _local_3 = (_local_3 - 48);

          _local_5 = 16;

          _local_6 = (_local_2 - 37);

          ESP = (_local_3 & -16);

          _local_7 = CModule.mallocString(_arg_1);

          _local_8 = _arg_1.length;

          do

          {

          var _local_9:int = (L__2E_str2 - _local_5);

          _local_9 = li8((_local_9 + 16)) /*FlasCC (Alchemy)*/ ;

          _local_3 = (_local_3 - 16);

          si32(_local_9, (_local_3 + 4)); //FlasCC (Alchemy)

          si32(_local_6, _local_3); //FlasCC (Alchemy)

          ESP = _local_3;

          F_sprintf();

          _local_3 = (_local_3 + 16);

          _local_5 = (_local_5 + -1);

          _local_6 = (_local_6 + 2);

          } while (_local_5 != 0);

          _local_3 = (_local_3 - 16);

          _local_9 = (_local_2 - 4);

          si32(_local_9, (_local_3 + 12)); //FlasCC (Alchemy)

          _local_9 = (_local_2 - 37);

          si32(_local_9, (_local_3 + 8)); //FlasCC (Alchemy)

          si32(_local_8, (_local_3 + 4)); //FlasCC (Alchemy)

          si32(_local_7, _local_3); //FlasCC (Alchemy)

          ESP = _local_3;

          F_get_sign();

          _local_3 = (_local_3 + 16);

          _local_5 = eax;

          _local_9 = li32((_local_2 - 4)) /*FlasCC (Alchemy)*/ ;

          _local_4 = CModule.readString(_local_5, _local_9);

          if (_local_7 != 0)

          {

          _local_3 = (_local_3 - 16);

          si32(_local_7, _local_3); //FlasCC (Alchemy)

          ESP = _local_3;

          F_IDAlloc();

          _local_3 = (_local_3 + 16);

          };

          if (_local_5 != 0)

          {

          _local_3 = (_local_3 - 16);

          si32(_local_5, _local_3); //FlasCC (Alchemy)

          ESP = _local_3;

          F_idalloc();

          _local_3 = (_local_3 + 16);

          };

          var _local_10 = _local_4;

          _local_3 = _local_2;

          ESP = _local_3;

          return (_local_10);

          }

          }//package com.bilibili.interfaces[/mw_shl_code]

          [mw_shl_code=actionscript3,true]public function getSign_v2(_arg_1:String, _arg_2:int):String

          {

          var _local_12:*;

          var _local_3:int;

          var _local_5 = null;

          var _local_6:int;

          var _local_11:int;

          var _local_8:int;

          var _local_10:int;

          var _local_9:int;

          var _local_4:int = ESP;

          _local_3 = _local_4;

          _local_4 = (_local_4 - 48);

          _local_6 = _arg_2;

          if (_local_6 >= 5)

          {

          _local_12 = _arg_1;

          }

          else

          {

          _local_8 = (L__2E_str2 + (_local_6 << 4));

          _local_9 = 16;

          _local_10 = (_local_3 - 37);

          ESP = (_local_4 & -16);

          _local_6 = CModule.mallocString(_arg_1);

          _local_11 = _arg_1.length;

          do

          {

          var _local_7:int = (_local_8 - _local_9);

          _local_7 = li8((_local_7 + 16)) /*FlasCC (Alchemy)*/ ;

          _local_4 = (_local_4 - 16);

          si32(_local_7, (_local_4 + 4)); //FlasCC (Alchemy)

          si32(_local_10, _local_4); //FlasCC (Alchemy)

          ESP = _local_4;

          F_sprintf();

          _local_4 = (_local_4 + 16);

          _local_9 = (_local_9 + -1);

          _local_10 = (_local_10 + 2);

          } while (_local_9 != 0);

          _local_4 = (_local_4 - 16);

          _local_7 = (_local_3 - 4);

          si32(_local_7, (_local_4 + 12)); //FlasCC (Alchemy)

          _local_7 = (_local_3 - 37);

          si32(_local_7, (_local_4 + 8)); //FlasCC (Alchemy)

          si32(_local_11, (_local_4 + 4)); //FlasCC (Alchemy)

          si32(_local_6, _local_4); //FlasCC (Alchemy)

          ESP = _local_4;

          F_get_sign();

          _local_4 = (_local_4 + 16);

          _local_10 = eax;

          _local_7 = li32((_local_3 - 4)) /*FlasCC (Alchemy)*/ ;

          _local_5 = CModule.readString(_local_10, _local_7);

          if (_local_6 != 0)

          {

          _local_4 = (_local_4 - 16);

          si32(_local_6, _local_4); //FlasCC (Alchemy)

          ESP = _local_4;

          F_idalloc();

          _local_4 = (_local_4 + 16);

          };

          if (_local_10 != 0)

          {

          _local_4 = (_local_4 - 16);

          si32(_local_10, _local_4); //FlasCC (Alchemy)

          ESP = _local_4;

          F_idalloc();

          _local_4 = (_local_4 + 16);

          };

          _local_12 = _local_5;

          };

          _local_4 = _local_3;

          ESP = _local_4;

          return (_local_12);

          }

          }//package com.bilibili.interfaces[/mw_shl_code]

          可以看到,二者代碼非常相似,而且光看代碼無(wú)法找到有用的信息,那么就得想辦法去調(diào)試了

          3.目前我只知道的辦法是:使用JPEXS反編譯軟件來(lái)修改SWF代碼(插Log),然后通過(guò)Fiddler劫持替換SWF,通過(guò)顯示Log信息來(lái)進(jìn)行調(diào)試?

          要顯示log信息就得安裝debug版本的flash

          http://www.adobe.com/support/flashplayer/debug_downloads.html

          ?

          為方便閱讀日志信息可以安裝Cygwin

          ?

          具體步驟我也是參考了http://blog.csdn.net/hot_vc/article/details/50600717這篇文章?

          ————————————————————————————————————————————————————————————————————————————

          將SWF載入JPEXS

          ?

          要想修改SWF的源碼就得去修改PCODE,第一次接觸這種也不是很懂,覺得有點(diǎn)類似于C#的IL代碼

          通過(guò)AS3代碼和PCODE代碼的一一進(jìn)行對(duì)比,還是能找到一些規(guī)律的

          為了查看代碼中變量值,用到以下代碼

          [mw_shl_code=javascript,true]findpropstrict Qname(PackageNamespace(""),"trace")

          getlocal 5

          callpropvoid Qname(PackageNamespace(""),"trace") 1[/mw_shl_code]

          這個(gè)代碼就相當(dāng)于trace(_loc5_);

          修改保存后利用Fiddler來(lái)劫持替換我們的SWF

          ?

          這樣Cygwin就能輸出我們想要看到的結(jié)果了。

          其中有些變量的值是地址,而不是數(shù)據(jù),為了讀取地址中的數(shù)據(jù),利用到了這句代碼CModule.readString(地址,讀取長(zhǎng)度);

          按照原PCODE的格式,寫出插LOG時(shí)的PCODE

          [mw_shl_code=asm,true]pushint 60

          setlocal 8

          getlex Qname(PackageNamespace("com.bilibili.interfaces"),"CModule")

          getlocal 7

          getlocal 8

          callproperty Qname(PackageNamespace(""),"readString") 2

          coerce_s

          setlocal 5

          findpropstrict Qname(PackageNamespace(""),"trace")

          getlocal 5

          callpropvoid Qname(PackageNamespace(""),"trace") 1[/mw_shl_code]

          此代碼相當(dāng)于

          _loc8_:int = 60;

          _loc5_:* = CModule.readString(_loc7_,_loc8_);

          trace(_loc5_);

          ?

          4.其實(shí)關(guān)鍵算法在F_get_sign()中,因?yàn)閺腇_get_sign()函數(shù)中出來(lái)后,eax中就已經(jīng)存放帶著sign的視頻URL的地址了。

          F_get_sign()函數(shù)過(guò)于復(fù)雜,總之通過(guò)不斷地插這兩種Log查看變量信息,最終找到了算法?

          ?

          由這個(gè)地方可以看出是MD5,還有一個(gè)位置能夠準(zhǔn)確地查看到進(jìn)行MD5處理的數(shù)據(jù)(已經(jīng)忘了.....)

          算法如下:

          五種清晰度

          qn=16,quality=1

          qn=32,quality=5

          qn=48,quality=2

          qn=64,quality=2

          qn=80,quality=3

          qn=112,quality=4

          三種類型的視頻bili2,bangumi,movie

          bili2:

          time = F_clock_gettime();//相當(dāng)于取一個(gè)時(shí)間隨機(jī)數(shù)

          sign = MD5(“cid=” + cid + “&player=1&qn=112&quality=4&ts=” + time + “1c15888dc316e05a15fdd0a02ed6584f”)

          url = “https://interface.bilibili.com/playurl?player=1&qn=112&cid=” + cid + “&quality=4&ts=” + time + “&sign=” + sign

          bangumi:

          time = F_clock_gettime();//相當(dāng)于取一個(gè)時(shí)間隨機(jī)數(shù)

          sign = MD5(“cid=” + cid + “&module=bangumi” + “&player=1” + “&qn=112” + “&quality=4” + “&ts=” + time + “9b288147e5474dd2aa67085f716c560d”)

          url = “https://bangumi.bilibili.com/player/web_api/playurl?cid=” + cid + “&player=1” + “&module=bangumi” + “&qn=112” + “&quality=4&ts=” + time + “&sign=” + sign

          movie:

          time = F_clock_gettime();//相當(dāng)于取一個(gè)時(shí)間隨機(jī)數(shù)

          sign = MD5(“cid=” + cid + “&module=movie” + “&player=1” + “&qn=112” + “&quality=4” + “&ts=” + time + “9b288147e5474dd2aa67085f716c560d”)

          url = “https://bangumi.bilibili.com/player/web_api/playurl?cid=” + cid + “&player=1” + “&module=movie” + “&qn=112” + “&quality=4&ts=” + time + “&sign=” + sign

          也就只分析到了這里?

          順便說(shuō)下,有些tx.acgvideo.com開頭的視頻無(wú)法下載是因?yàn)榉?wù)器檢查了Refer,只要在協(xié)議頭里面加入Refer:[media]https://static.hdslb.com/play.swf[/media],就能下載了

          水平有限,分析若有什么錯(cuò)誤,大家看著辦吧

          歡迎大家在評(píng)論區(qū)留下你的意見。謝謝 諸葛商學(xué)院

          家好,今天小編就以B站為例,帶大家爬取視頻,學(xué)會(huì)之后你也能爬取你想要的視頻!或不多說(shuō),上正文

          爬蟲用的好,牢飯吃的早!

          本文僅作知識(shí)分享,切勿用于違法行為!

          下載倉(cāng)庫(kù)

          git@github.com:inspurer/PythonSpider.git
          或者直接下載:https://github.com/inspurer/PythonSpider/tree/master/bilibili

          替換

          隨便打開一個(gè)b站的界面,比如

          將url復(fù)制到代碼中去,運(yùn)行代碼,稍等一會(huì)兒,上述圖中的視頻就被下載下來(lái)了。

          How to Code

          分析網(wǎng)頁(yè)源碼

          按f12瀏覽器開發(fā)者工具 ,通過(guò)一番審查,我們定位到視頻的url在網(wǎng)頁(yè)源代碼的位置如下:

          window.__playinfo__={
          "from":"local",
          "result":"suee",
          "quality":32,
          "format":"flv480",
          "timelength":408884,
          "accept_format":"flv720,flv480,flv360",
          "accept_description":["高清 720P","清晰 480P","流暢 360P"],
          "accept_quality":[64,32,15],
          "video_codecid":7,
          "video_project":true,
          "seek_param":"start",
          "seek_type":"offset",
          "durl":[{"order":1,"length":408884,"size":42782550,"ahead":"EhA=","vhead":"AWQAHv/hAB5nZAAerNlA2D3n//AoACfxAAADAAEAAAMAMA8WLZYBAAVo6+zyPA==",
          "url":"http://upos-hz-mirrorkodo.acgvideo.com/upgcxcode/48/61/45596148/45596148-1-32.flv?e=ig8euxZM2rNcNbRa7b4VhoMz7WhjhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IB5QK==&deadline=1543136253&dynamic=1&gen=playurl&oi=1862807981&os=kodo&platform=pc&rate=176800&trid=69ea1a81ac21448f9e2189ef479a2d6d&uipk=5&uipv=5&um_deadline=1543136253&um_sign=c479f3fd3075b359d0a04e5eb584ac55&upsig=1c05ca3838af92d2c1411cf3000e8345http://upos-hz-mirrorkodo.acgvideo.com/upgcxcode/48/61/45596148/45596148-1-32.flv?e=ig8euxZM2rNcNbRa7b4VhoMz7WhjhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IB5QK==&deadline=1543136253&dynamic=1&gen=playurl&oi=1862807981&os=kodo&platform=pc&rate=176800&trid=69ea1a81ac21448f9e2189ef479a2d6d&uipk=5&uipv=5&um_deadline=1543136253&um_sign=c479f3fd3075b359d0a04e5eb584ac55&upsig=1c05ca3838af92d2c1411cf3000e8345","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/48/61/45596148/45596148-1-32.flv?um_deadline=1543136253&platform=pc&rate=176800&oi=1862807981&um_sign=c479f3fd3075b359d0a04e5eb584ac55&gen=playurl&os=cos&trid=69ea1a81ac21448f9e2189ef479a2d6d"]}]}

          最后的url就是我們想要的結(jié)果。
          如果在瀏覽器中查找不方便的話,我們可以把通過(guò)代碼把網(wǎng)頁(yè)源碼輸出到本地

          response = requests.get(url='https://www.bilibili.com/video/av26522634', headers= self.getHtmlHeaders)
                  print(response.status_code)
                  if response.status_code == 200:
                      print(response.text)

          為了偽裝成瀏覽器,我們需要在reqests添加Headers
          這個(gè)Headers需要我們?nèi)g覽器中手動(dòng)獲取
          切換到NetWork標(biāo)簽下,再選擇Headers,

             self.getHtmlHeaders={
                  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
                  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
                  'Accept-Encoding': 'gzip, deflate, br',
                  'Accept-Language': 'zh-CN,zh;q = 0.9'
              }

          這里只選擇了幾個(gè)關(guān)鍵的

          解析得到視頻地址

          根據(jù)上一步分析,我們得到了網(wǎng)頁(yè)的源碼,并在源碼中定位到了視頻地址,接下來(lái),我們就用代碼自動(dòng)獲取這個(gè)地址了

          #用正則、json得到視頻url;用pq失敗后的無(wú)奈之舉
          pattern = r'\<script\>window\.__playinfo__=(.*?)\</script\>'
          result = re.findall(pattern, html)[0]
          temp = json.loads(result)
          #temp['durl']是一個(gè)列表,里面有很多字典
          #video_url = temp['durl']
          for item in temp['data']['durl']:
          	if 'url' in item.keys():
          		video_url = item['url']

          順便獲取下視頻的名字:

          #用pq解析得到視頻標(biāo)題
          doc = pq(html)
          video_title = doc('#viewbox_report > h1 > span').text()然后組合返回下:

          然后組合返回下:

          return{
           'title': video_title,
           'url': video_url
           }

          下載視頻

          通過(guò)在開發(fā)者工具中搜索關(guān)鍵詞,比如上面得到的視頻url,我們可以定位到在瀏覽器中真正下載視頻的請(qǐng)求在哪

          然后把它的Headers添加到reqests中,就可以下載視頻了

           with open(filename, "wb") as f:
           	 f.write(requests.get(url=url, headers=self.downloadVideoHeaders, stream=True, verify=False).content)

          你下載的視頻在本地播放不了,請(qǐng)不要試圖修改源代碼中保存文件的格式由.flv改成.mp4,因?yàn)閎站的視頻本來(lái)就是flv格式的,需要用特殊的視頻播放器播放,這里推薦一個(gè)無(wú)毒無(wú)害的KMPlayer,鏈接:https://pan.baidu.com/s/1O4-Uia04Vm-jbUjyrVWfkw 提取碼:4l11

          結(jié)尾

          最后多說(shuō)一句,小編是一名python開發(fā)工程師,這里有我自己整理了一套最新的python系統(tǒng)學(xué)習(xí)教程,包括從基礎(chǔ)的python腳本到web開發(fā)、爬蟲、數(shù)據(jù)分析、數(shù)據(jù)可視化、機(jī)器學(xué)習(xí)等。想要這些資料的可以關(guān)注小編,并在后臺(tái)私信小編:“01”即可領(lǐng)取。


          本文的文字及圖片來(lái)源于網(wǎng)絡(luò)加上自己的想法,僅供學(xué)習(xí)、交流使用,不具有任何商業(yè)用途,版權(quán)歸原作者所有,如有問(wèn)題請(qǐng)及時(shí)聯(lián)系我們以作處理。


          主站蜘蛛池模板: 无码国产精品一区二区免费3p| 亚洲片国产一区一级在线观看| 成人免费一区二区三区| 蜜桃臀无码内射一区二区三区| 日韩精品久久一区二区三区| 国产另类TS人妖一区二区| 国产人妖在线观看一区二区| 日韩国产精品无码一区二区三区| 午夜无码视频一区二区三区| 亚洲AV香蕉一区区二区三区| 午夜福利一区二区三区高清视频| av无码精品一区二区三区四区| 亚洲日韩精品国产一区二区三区| 午夜福利一区二区三区在线观看 | 欧美日韩一区二区成人午夜电影 | 亚洲国模精品一区| 国产在线精品一区二区在线看| 综合无码一区二区三区四区五区 | 激情内射亚州一区二区三区爱妻| 另类ts人妖一区二区三区| 国产精品一区在线麻豆| 99精品一区二区三区无码吞精 | 亚洲一区二区高清| 国产成人免费一区二区三区 | 日韩精品无码一区二区三区免费 | 好看的电影网站亚洲一区| 国产成人无码一区二区三区在线 | 91视频国产一区| 亚洲成在人天堂一区二区| 无码日韩精品一区二区免费暖暖| 国偷自产av一区二区三区| 中文字幕一区二区人妻| 亚洲一区无码中文字幕| 国产精品免费一区二区三区四区 | 亚洲AⅤ无码一区二区三区在线| 国产一区二区在线|播放| 精品一区二区三区影院在线午夜| 天堂一区二区三区精品| 无码一区二区三区在线| 在线视频国产一区| 国产精品亚洲产品一区二区三区|