1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 7339字,需瀏覽 15分鐘

         ·

        2021-05-21 18:45

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

        初探

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

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

        Tokyo真的有那么hot? 

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

        我和狗子說“等著吧” 

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

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

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

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

        自己動手,豐衣足食!


        環(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瀏覽器打開 

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

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

        大概界面是這樣


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

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

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

        顯然視頻就放在這個這個video-player中 

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

        Easy好吧! 

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


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


        What???

        這是什么???

        為啥這么小???


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


        Network Traffic


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

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

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

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


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

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

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

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

         

        知識點(diǎn)!這都是知識點(diǎn)?。ㄇ煤诎澹。?/span>

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


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


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

        9s。。。。。 

        每一個小視頻只有9s,難道要一個又一個的去復(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)什么時候結(jié)束呢?也就是說我怎么知道i的大小呢? 

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

        在開發(fā)者模式中再次回到Element選項(xiàng)卡,定位到視頻框右下角的時間,標(biāo)簽為duration,這里的時間格式是 時:分:秒格式的,我們可以計(jì)算得到總時長的秒數(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é),而且下了兩百多個之后出現(xiàn)了拒絕訪問錯誤。


        動態(tài)代理


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

        主要代碼如下所示 


        合并文件


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


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

        執(zhí)行


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

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

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


        成果如下

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


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

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


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

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

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


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


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


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


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


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


        pip install m3u8

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

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


        現(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)這個的幾個關(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("下載完成!總共耗時 %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ī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            成人中文字幕在线 | 日本精品在线观看 | 九色丨PORNY丨自拍蝌蚪 处一女一级a一片视频 | 三p被狂躁到高潮失禁 | 国产aaaaaaa | 日韩在线视频播放 | 人人澡人人添人人玩软件下载 | 熟女视频网站 | 日韩中文字幕在线免费观看 | 国产一级a爱做片免费☆观看 |