<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python爬蟲教程:Python爬取視頻之日本愛情電影

          共 7339字,需瀏覽 15分鐘

           ·

          2021-05-21 18:45

          肉身翻墻后,感受一下外面的骯臟世界。墻內(nèi)的朋友叫苦不迭,由于某些原因,VPN能用的越來越少。上周我的好朋友狗子和我哭訴說自己常用的一個(gè)VPN終于也壽終正寢了,要和眾多的日本小姐姐說再見了。作為“外面人”,我還是要幫他一把……

          初探

          狗子給我的網(wǎng)站還算良心,只跳了五個(gè)彈窗就消停了。 

          然后看到的就是各種穿不起衣服的女生的賣慘視頻,我趕緊閉上眼睛,默念了幾句我佛慈悲。 

          Tokyo真的有那么hot? 

          給狗子發(fā)了一張大的截圖,狗子用涂鴉給我圈出了其中一個(gè)。 

          我和狗子說“等著吧” 

          (放心網(wǎng)站截圖我是打了碼也不敢放的。。。)

          點(diǎn)進(jìn)去之后,可以在線播放。 

          右下角有一個(gè) Download 按鈕,點(diǎn)擊之后需要注冊付費(fèi)。 

          當(dāng)時(shí)我就火了,這種賣慘視頻毒害我兄弟精神,還敢收錢?! 

          自己動手,豐衣足食!


          環(huán)境 & 依賴


          Win10 64bit 

          IDE: PyCharm 

          Python 3.6 

          python-site-packegs: requests + BeautifulSoup + lxml + re + m3u8


          在已經(jīng)安裝pip的環(huán)境下均可直接命令行安裝


          網(wǎng)站解析


          將鏈接復(fù)制到Chrome瀏覽器打開 

          (我平時(shí)用獵豹,也是Chrome內(nèi)核,界面比較舒服,但是這個(gè)時(shí)候必須大喊一聲谷歌大法好) 

          菜單——更多工具——開發(fā)者選項(xiàng)(或者快捷鍵F12)進(jìn)入Chrome內(nèi)置的開發(fā)者模式 

          大概界面是這樣


          (唉打碼真的累。。。。) 

          然后,根據(jù)提示,逐層深入標(biāo)簽找到視頻的具體位置 

          這個(gè)網(wǎng)站存放的位置是 …->flash->video_container->video-player 

          顯然視頻就放在這個(gè)這個(gè)video-player中 

          在這個(gè)標(biāo)簽中,有一個(gè)名字為 source 的鏈接,src=”http://#%@就不告訴你#@¥” 

          Easy好吧! 

          這點(diǎn)小把戲還難得到我?我已經(jīng)準(zhǔn)備和狗子要紅包了 


          復(fù)制該鏈接到地址欄粘貼并轉(zhuǎn)到,然后,神奇的一幕出現(xiàn)了!!


          What???

          這是什么???

          為啥這么小???


          科普概念如上,那也就是說,m3u8記錄了真實(shí)的視頻所在的地址。


          Network Traffic


          想要從源碼直接獲得真實(shí)下載地址怕是行不通了。 

          這時(shí)候再和我一起讀“谷歌大法好!” 

          很簡單,瀏覽器在服務(wù)器中Get到視頻呈現(xiàn)到我們面前,那這個(gè)過程必定經(jīng)過了解析這一步。 

          那我們也可以利用瀏覽器這個(gè)功能來進(jìn)行解析


          依舊在開發(fā)者模式,最上面一行的導(dǎo)航欄,剛剛我們在Elements選項(xiàng)卡,現(xiàn)在切換到Network 

          我們監(jiān)聽視頻播放的時(shí)候的封包應(yīng)該就可以得到真實(shí)的視頻地址了,試試看!

          我們驚喜的發(fā)現(xiàn),一個(gè)又一個(gè)的 .ts 文件正在載入了 

          (如果在圖片里發(fā)現(xiàn)任何url請友情提醒我謝謝不然怕是水表難保)

           

          知識點(diǎn)!這都是知識點(diǎn)!(敲黑板!)

          點(diǎn)開其中的一個(gè).ts文件看一下 


          這里可以看到請求頭,雖然url被我走心的碼掉了,但這就是真實(shí)的視頻地址了


          復(fù)制這個(gè)URL到地址欄,下載 

          9s。。。。。 

          每一個(gè)小視頻只有9s,難道要一個(gè)又一個(gè)的去復(fù)制嗎?


          視頻片段爬取


          答案是當(dāng)然不用。 

          這里我們要請出網(wǎng)絡(luò)數(shù)據(jù)采集界的裝逼王:Python爬蟲!!!



          首先進(jìn)行初始化,包括路徑設(shè)置,請求頭的偽裝等。


          采集部分主要是將requests的get方法放到了for循環(huán)當(dāng)中 

          這樣做可行的原因在于,在Network監(jiān)聽的圖中我們可以看到.ts文件的命名是具有規(guī)律的 seg-i-v1-a1,將i作為循環(huán)數(shù)


          那么問題又來了,我怎么知道循環(huán)什么時(shí)候結(jié)束呢?也就是說我怎么知道i的大小呢? 

          等等,我好像記得在視頻播放的框框右下角有時(shí)間來著? 

          在開發(fā)者模式中再次回到Element選項(xiàng)卡,定位到視頻框右下角的時(shí)間,標(biāo)簽為duration,這里的時(shí)間格式是 時(shí):分:秒格式的,我們可以計(jì)算得到總時(shí)長的秒數(shù) 

          但是呢,這樣需要我們先獲取這個(gè)時(shí)間,然后再進(jìn)行字符串的拆解,再進(jìn)行數(shù)學(xué)運(yùn)算,太復(fù)雜了吧,狗子已經(jīng)在微信催我了 

          Ctrl+F全局搜索duration 

          Yes!!!


          好了,可以點(diǎn)擊運(yùn)行然后去喝杯咖啡,哦不,我喜歡喝茶。

          一杯茶的功夫,回來之后已經(jīng)下載完成。我打開文件夾check一下,發(fā)現(xiàn)從編號312之后的clip都是只有573字節(jié),打開播放的話,顯示的是數(shù)據(jù)損壞。 

          沒關(guān)系,從312開始繼續(xù)下載吧。然而下載得到的結(jié)果還是一樣的573字節(jié),而且下了兩百多個(gè)之后出現(xiàn)了拒絕訪問錯(cuò)誤。


          動態(tài)代理


          顯然我的IP被封了。之前的多個(gè)小項(xiàng)目,或是因?yàn)榫W(wǎng)站防護(hù)不夠嚴(yán)格,或是因?yàn)閿?shù)據(jù)條目數(shù)量較少,一直沒有遇到過這種情況,這次的數(shù)據(jù)量增加,面對這種情況采取兩種措施,一種是休眠策略,另一種是動態(tài)代理。現(xiàn)在我的IP已經(jīng)被封了,所以休眠也為時(shí)已晚,必須采用動態(tài)IP了。 

          主要代碼如下所示 


          合并文件


          然后,我們得到了幾百個(gè)9s的.ts小視頻


          然后,在cmd命令行下,我們進(jìn)入到這些小視頻所在的路徑 

          執(zhí)行


          copy/b %s\*.ts %s\new.ts

          很快,我們就得到了合成好的視頻文件 

          當(dāng)然這個(gè)前提是這幾百個(gè).ts文件是按順序排列好的。


          成果如下

          優(yōu)化—調(diào)用DOS命令 + 解析m3u8


          為了盡可能的減少人的操作,讓程序做更多的事 

          我們要把盡量多的操作寫在code中


          引用os模塊進(jìn)行文件夾切換,在程序中直接執(zhí)行合并命令 

          并且,在判斷合并完成后,使用清除幾百個(gè)ts文件

          這樣,我們運(yùn)行程序后,就真的可以去喝一杯茶,回來之后看到的就是沒有任何多余的一個(gè)完整的最終視頻


          也就是說,要獲得一個(gè)完整的視頻,我們現(xiàn)在需要輸入視頻網(wǎng)頁鏈接,還需要使用chrome的network解析得到真實(shí)下載地址。第二個(gè)部分顯然不夠友好,還有提升空間。


          所以第一個(gè)嘗試是,可不可以有一個(gè)工具或者一個(gè)包能嗅探到指定網(wǎng)頁的network traffic,因?yàn)槲覀儎倓傄呀?jīng)看到真實(shí)地址其實(shí)就在requestHeader中,關(guān)鍵在于怎樣讓程序自動獲取。


          查閱資料后,嘗試了Selenium + PhantomJS的組合模擬瀏覽器訪問,用一個(gè)叫做browsermobProxy的工具嗅探保存HAR(HTTP archive)。在這個(gè)上面花費(fèi)了不少時(shí)間,但是關(guān)于browsermobProxy的資料實(shí)在是太少了,即使是在google上,搜到的也都是基于java的一些資料,面向的python的API也是很久沒有更新維護(hù)了。此路不通。


          在放棄之前,我又看一篇網(wǎng)站的源碼,再次把目光投向了m3u8,上面講到這個(gè)文件應(yīng)該是包含文件真實(shí)地址的索引,索引能不能把在這上面做些文章呢?


          Python不愧是萬金油語言,packages多到令人發(fā)指,m3u8處理也是早就有熟肉。


          pip install m3u8

          這是一個(gè)比較小眾的包,沒有什么手冊,只能自己讀源碼。

          這個(gè)class中已經(jīng)封裝好了不少可以直接供使用的數(shù)據(jù)類型,回頭抽時(shí)間可以寫一寫這個(gè)包的手冊。


          現(xiàn)在,我們可以從requests獲取的源碼中,首先找到m3u8的下載地址,首先下載到本地,然后用m3u8包進(jìn)行解析,獲取真實(shí)下載地址。


          并且,解析可以得到所有地址,意味著可以省略上面的獲取duration計(jì)算碎片數(shù)目的步驟。


          最終


          最終,我們現(xiàn)在終于可以,把視頻網(wǎng)頁鏈接丟進(jìn)url中,點(diǎn)擊運(yùn)行,然后就可以去喝茶了。 


          再來總結(jié)一下實(shí)現(xiàn)這個(gè)的幾個(gè)關(guān)鍵點(diǎn): 

          - 網(wǎng)頁解析 

          - m3u8解析 

          - 動態(tài)代理設(shè)置 

          - DOS命令行的調(diào)用


          動手是最好的老師,尤其這種網(wǎng)站,兼具趣味性和挑戰(zhàn)性,就是身體一天不如一天。。。


          完整代碼

          # -*- coding:utf-8 -*-import requestsfrom bs4 import BeautifulSoupimport osimport lxmlimport timeimport randomimport reimport m3u8
          class ViedeoCrawler(): def __init__(self): self.url = "" self.down_path = r"F:\Spider\VideoSpider\DOWN" self.final_path = r"F:\Spider\VideoSpider\FINAL" try: self.name = re.findall(r'/[A-Za-z]*-[0-9]*',self.url)[0][1:] except: self.name = "uncensord" self.headers = { 'Connection': 'Keep-Alive', 'Accept': 'text/html, application/xhtml+xml, */*', 'Accept-Language': 'en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3', 'User-Agent':'Mozilla/5.0 (Linux; U; Android 6.0; zh-CN; MZ-m2 note Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 MZBrowser/6.5.506 UWS/2.10.1.22 Mobile Safari/537.36' }
          def get_ip_list(self): print("正在獲取代理列表...") url = 'http://www.xicidaili.com/nn/' html = requests.get(url=url, headers=self.headers).text soup = BeautifulSoup(html, 'lxml') ips = soup.find(id='ip_list').find_all('tr') ip_list = [] for i in range(1, len(ips)): ip_info = ips[i] tds = ip_info.find_all('td') ip_list.append(tds[1].text + ':' + tds[2].text) print("代理列表抓取成功.") return ip_list
          def get_random_ip(self,ip_list): print("正在設(shè)置隨機(jī)代理...") proxy_list = [] for ip in ip_list: proxy_list.append('http://' + ip) proxy_ip = random.choice(proxy_list) proxies = {'http': proxy_ip} print("代理設(shè)置成功.") return proxies
          def get_uri_from_m3u8(self,realAdr): print("正在解析真實(shí)下載地址...") with open('temp.m3u8', 'wb') as file: file.write(requests.get(realAdr).content) m3u8Obj = m3u8.load('temp.m3u8') print("解析完成.") return m3u8Obj.segments
          def run(self): print("Start!") start_time = time.time() os.chdir(self.down_path) html = requests.get(self.url).text bsObj = BeautifulSoup(html, 'lxml') realAdr = bsObj.find(id="video-player").find("source")['src']
          # duration = bsObj.find('meta', {'property': "video:duration"})['content'].replace("\"", "") # limit = int(duration) // 10 + 3
          ip_list = self.get_ip_list() proxies = self.get_random_ip(ip_list) uriList = self.get_uri_from_m3u8(realAdr) i = 1 # count for key in uriList: if i%50==0: print("休眠10s") time.sleep(10) if i%120==0: print("更換代理IP") proxies = self.get_random_ip(ip_list) try: resp = requests.get(key.uri, headers = self.headers, proxies=proxies) except Exception as e: print(e) return if i < 10: name = ('clip00%d.ts' % i) elif i > 100: name = ('clip%d.ts' % i) else: name = ('clip0%d.ts' % i) with open(name,'wb') as f: f.write(resp.content) print('正在下載clip%d' % i) i = i+1 print("下載完成!總共耗時(shí) %d s" % (time.time()-start_time)) print("接下來進(jìn)行合并……") os.system('copy/b %s\\*.ts %s\\%s.ts' % (self.down_path,self.final_path, self.name)) print("合并完成,請您欣賞!") y = input("請檢查文件完整性,并確認(rèn)是否要刪除碎片源文件?(y/n)") if y=='y': files = os.listdir(self.down_path) for filena in files: del_file = self.down_path + '\\' + filena os.remove(del_file) print("碎片文件已經(jīng)刪除完成") else: print("不刪除,程序結(jié)束。")
          if __name__=='__main__': crawler = ViedeoCrawler() crawler.run()

          搜索下方加老師微信

          老師微信號:XTUOL1988切記備注學(xué)習(xí)Python

          領(lǐng)取Python web開發(fā),Python爬蟲,Python數(shù)據(jù)分析,人工智能等精品學(xué)習(xí)課程。帶你從零基礎(chǔ)系統(tǒng)性的學(xué)好Python!

          源自:https://blog.csdn.net/JosephPai/article/

          聲明:文章著作權(quán)歸作者所有,如有侵權(quán),請聯(lián)系小編刪除


          瀏覽 111
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产大尺度视频 | 五月天色色网址 | 国产黄色视频在线观看免费 | 逼特逼免费视频 | 国产女主播在线 |