2021141 2021-2022-2 《Python程式設計》實驗四報告
2021141 2021-2022-2 《Python程式設計》實驗四報告
課程:《Python程式設計》
班級: 2114
姓名: 楊雲泰
學號:20211401
實驗教師:wzq
實驗日期:2022年5月23日
必修/選修: 公選課
1.實驗要求
Python綜合應用:爬蟲、資料處理、視覺化、機器學習、神經網路、遊戲、網路安全等。
課代表和各小組負責人收集作業(原始碼、視訊、綜合實踐報告)
注:在華為ECS伺服器(OpenOuler系統)和物理機(Windows/Linux系統)上使用VIM、PDB、IDLE、Pycharm等工具程式設計實現。
批閱:注意本次實驗不算做實驗總分,前三個實驗每個實驗10分,累計30分。本次實踐算入綜合實踐,打分為25分。
評分標準:
(1)程式能執行,功能豐富。(需求提交原始碼,並建議錄製程式執行的視訊)10分
(2)綜合實踐報告,要體現實驗分析、設計、實現過程、結果等資訊,格式規範,邏輯清晰,結構合理。10分。
(3)在實踐報告中,需要對全課進行總結,並寫課程感想體會、意見和建議等。5分
(4)如果沒有使用華為雲服務(ECS或者MindSpore均可),本次實踐扣10分。
注意:每個人的實驗不能重複,課代表先統計大家做的內容並彙總,有重複的需要自行協商。
2.實驗分析及設計過程
- 主要內容:爬取91看劇網視訊、解密ts片段、合併上千條ts檔案成、MP4檔案。(用非同步協程的方式)
一、分析,程式設計
1、爬取下載91視訊網
1.1分析91視訊網原始碼,做出爬取策略獲得m3u8檔案。
- m3u8檔案作用:用來儲存每一個視訊片段url的檔案,包含了上千個.ts檔案地址。
分析網頁原始碼
發現有兩處有m3u8的url,經過驗證發現url":"https://iqiyi.sd-play.com/20211117/BjOG4OZ8/index.m3u8
訪問該url發現其指向的是另一個m3u8的部分url(如圖)
發現只要把這一部分url與第一個m3u8檔案的url進行合併剪接可獲得第二個麼m3u8檔案url。
訪問該url發現找到了.ts下載路徑
- 訪問每一個url可獲得一個小片段的.ts檔案
如果僅使用單執行緒,由於需要上千次的oi操作會導致下載速度極慢,故需要用非同步協程的方式加快下載速度。
又由於非同步協程方式是亂序下載切所給url沒有任何規律可言,故需重新命名排序,避免片段混亂無法合併。
- 流程圖如下
看似很簡單,實則會碰到很多困難。
1.2程式碼實現
- 使用的庫
import requests
import re
import aiohttp
import aiofiles
import asyncio
- 本次由於程式複雜,使用了函式進行包裝,程式如下(點選開啟):
主函式
if __name__=='__main__':
url = 'http://91kj.vip/vodplay/180551-4-1.html'
main(url)
def main(url):
m3u8_f_url=get_m3u8_url(url)
get_m3u8(m3u8_f_url)
m3u8url = dow_m3u8(m3u8_f_url)
asyncio.run(aio_download())
訪問網址獲得原始碼,正則提取m3u8 url地址
def get_m3u8_url(url):
res = requests.get(url)
obj = re.compile(r'"},"url":"(?P<uur>.*?)","url_next":',re.S)
ul = obj.search(res.text).groups('uur')
ul=clean(ul)
return ul
下載第一個m3u8檔案,儲存在本地
def get_m3u8(url):
res = requests.get(url)
with open('first.m3u8',mode='wb') as f:
f.write(res.content)
拼接獲取第二個m3u8 url,下載第二個檔案
def dow_m3u8(url):
with open('first.m3u8',mode='r') as f:
for i in f:
if i.startswith("#"):
continue
else:
i.split()
url_hou=i.split('/',3)[3]
url_qian=url.split('index.m3u8')[0]
urlre= url_qian+url_hou
with open("second.m3u8",mode="wb") as f:
hed = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.62',
}
resp = requests.get(urlre,headers=hed)
f.write(resp.content)
return urlre
非同步協程下載ts檔案,並重新命名,生成名字目錄list.txt
def modify_text():
with open('list.txt', "r+") as f:
f.seek(0)
f.truncate()
def write(list):
with open ("list.txt",mode="a+") as f:
f.write(list)
async def download_ts(url,name,session):
async with session.get(url) as resp:
async with aiofiles.open(f"lyb/{name}",mode='wb') as f:
await f.write(await resp.content.read())
print(f'{name}下載完畢')
async def aio_download():
"""執行非同步操作 """
n = 1
tasks = []
async with aiohttp.ClientSession() as session:
async with aiofiles.open('second.m3u8',mode='r',encoding='utf-8') as f:
modify_text()
async for line in f:
line = line.strip()
if line.startswith('#'):
continue
name = f"{n}.ts"
names = name+"\n"
write(names)
n += 1
task = asyncio.create_task(download_ts(line,name,session))
tasks.append(task)
await asyncio.wait(tasks)
- 第一部分完成。
2、解密ts檔案
2.1 分析
開啟第二個m3u8檔案可見:
ts檔案被進行了加密
開啟key的url可見:
其中有金鑰
- 流程圖如下
2.2程式碼實現
- 使用的庫
import requests
import re
import aiohttp
import aiofiles
import asyncio
from Crypto.Cipher import AES
- AES用來解密
程式碼:
得到key的url
key_url = m3u8url.split('index.m3u8')[0]+"key.key"
(點選開啟)
訪問爬取key
def get_ket(url):
res = requests.get(url)
res.encoding="utf-8"
return res.text
非同步解密
async def aio_dec(key):
tasks=[]
async with aiofiles.open("list.txt",mode="r") as f:
async for i in f:
i= i.strip()
task = asyncio.create_task(dec_ts(i,key))
tasks.append(task)
await asyncio.wait(tasks)
async def dec_ts(name,key):
aes = AES.new(key=key.encode('utf-8'), IV=b"0000000000000000",mode=AES.MODE_CBC)
async with aiofiles.open(f"lyb/{name}",mode="rb") as f1,\
aiofiles.open(f"temp_lyb/{name}",mode="wb") as f2:
bs = await f1.read()
await f2.write(aes.decrypt(bs))
print(f"{name}完成")
3、合併ts檔案
這部分我是用的是windows的cmd命令進行合併
mac也可找到相應de命令
由於ts檔案有上千個,如果一次合成會導致命令過長,執行不成功,經過測試發現在500左右的檔案是剛好的。
進行分批合併後再進行合併,生成完整視訊。
- 程式碼如下(點選開啟):
程式碼
def make(list,name):
s = '+'.join(list)
os.system(f"cd temp_lyb & copy /b {s} {name}.mp4")
print(f"over{name}")
def merge_ts():
lst = []
lst2 = []
n=1
with open("list.txt",mode="r",encoding="utf-8") as f:
for i in f:
i = i.strip()
lst.append(f'{i}')
if len(lst)==650:
make(lst,n)
n+=1
lst = []
make(lst,n)
for j in range(n):
j+=1
lst2.append(f'{j}.mp4')
make(lst2,'over')
程式碼執行
除錯華為雲
- 1.建立新的華為雲
- 2.在華為雲上下載python3.9版本
- 3.安裝對應的庫
- 4.執行結果
在華為雲上的檔案:
未解密的:
加密後的:
3.實驗過程中的問題:
1.第二個m3u8檔案中的url沒有順序,爬到的無法排序。
重新名命排序,生成命名後的檔案進行傳遞。
2.在合併第二個m3u8檔案時無法用re擷取到對應的url
改變方法,用split()
3.在下載ts檔案時,非同步模組報錯但能下載到所有ts檔案
發現在Linux上面執行正常不報錯,研究了兩天,還不知道咋錯了,但可以爬到內容,可能是庫的問題,就這樣了。
4.發現華為雲上python是2.7版本,無法使用
網上找升級的教程,重新安裝python3.9
5.在爬取別的一些視訊時發現第二個m3u8檔案的url正確但無法爬取
經過反覆測試,不同源的視訊有些無法爬到,閃電線上的源可完全正常使用。
6.合併視訊的程式碼過長,無法執行。
進行分段合併讓後再合併一次得到完整視訊。
4.課程體會
在本學期的課上,老師教了python的基礎語法:
- 變數賦值
- 運算子及其優先順序
- 基本資料型別
- 迴圈語句
- 列表、元組、字典、集合
- 字串與正則表示式
- 函式
- 面向物件程式設計
- 檔案操作及異常處理
也學了一些對於python的應用: - Python操作資料庫
- Python爬蟲
- Socket套接字(TCP/UDP)進行通訊
對於python的學習,我從上學期已經開始了,在假期也一直再學習python,也看了一些關於python的書,也按照書上的內容,自己製作了一個pygame的小遊戲,在這過程中使我受益匪淺。也在開學之後的藍橋杯python比賽中,獲得了名次。
而這個課程對於我來說,課上的內容我已經都學完了,但這個課讓我更一次鞏固了我的python知識,這門課老師從由淺入深,逐步講解,相較自學而言更加有系統和條理,能讓新手知道從何入手,怎樣學習。對於我而言,這門課使我更加深入的學習了爬蟲的一些相關知識,學了re正則表達,bs4查詢以及lxml的應用,並且初步嘗試了非同步操作,使我受益良多。
對於課堂的建議:
1.我覺得可以在增加課上測試,在講完之後直接用雲班課考察,及時知道自己的不足。
2.增加課下實踐的此數,比如增加一些程式設計小作業,來增加程式設計的熟練度。
3.建議老師給一些學習路徑,比如要學爬蟲或機器學習等時,要從何學起,推薦一些基礎的書籍來給新手入門,增加一些學習路徑。
- 人生苦短,我用python
- 人生苦短,我用python
- 人生苦短,我用python