2.1 內建模組和開發規範
內建模組和開發規範
目標:掌握常見的內建模組的使用及瞭解軟體開發的規範。
今日概要:
- 內建模組
- json
- time
- datetime
- re
- 開發規範
- 主檔案
- 配置檔案
- 資料
- 附件
- 業務程式碼
1. 內建模組
1.1 json
json模組,是python內部的一個模組,可以將python的資料格式 轉換為json格式的資料,也可以將json格式的資料轉換為python的資料格式。
json格式,是一個數據格式(本質上就是個字串,常用語網路資料傳輸)
# Python中的資料型別的格式 data = [ {"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18}, ('wupeiqi',123), ] # JSON格式 value = '[{"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18},["wupeiqi",123]]'
1.1.1 核心功能
json格式的作用?
跨語言資料傳輸,例如:
A系統用Python開發,有列表型別和字典型別等。
B系統用Java開發,有陣列、map等的型別。
語言不同,基礎資料型別格式都不同。
為了方便資料傳輸,大家約定一個格式:json格式,每種語言都是將自己資料型別轉換為json格式,也可以將json格式的資料轉換為自己的資料型別。
Python資料型別與json格式的相互轉換:
-
資料型別 -> json ,一般稱為:序列化
import json data = [ {"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18}, ] res = json.dumps(data) print(res) # '[{"id": 1, "name": "\u6b66\u6c9b\u9f50", "age": 18}, {"id": 2, "name": "alex", "age": 18}]' res = json.dumps(data, ensure_ascii=False) print(res) # '[{"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18}]'
-
json格式 -> 資料型別,一般稱為:反序列化
import json data_string = '[{"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18}]' data_list = json.loads(data_string) print(data_list)
練習題
-
寫網站,給使用者返回json格式資料
-
安裝flask模組,協助我們快速寫網站(之前已安裝過)
pip3 install flask
-
使用flask寫網站
import json from flask import Flask app = Flask(__name__) def index(): return "首頁" def users(): data = [ {"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18}, ] return json.dumps(data) app.add_url_rule('/index/', view_func=index, endpoint='index') app.add_url_rule('/users/', view_func=users, endpoint='users') if __name__ == '__main__': app.run()
-
-
傳送網路請求,獲取json格式資料並處理。
import json import requests url = "https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=5&page_start=20" res = requests.get( url=url, headers={ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" } ) # json格式 print(res.text) # json格式轉換為python資料型別 data_dict = json.loads(res.text) print(data_dict)
1.1.2 型別要求
python的資料型別轉換為 json 格式,對資料型別是有要求的,預設只支援:
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
data = [
{"id": 1, "name": "武沛齊", "age": 18},
{"id": 2, "name": "alex", "age": 18},
]
其他型別如果想要支援,需要自定義JSONEncoder
才能實現【目前只需要瞭解大概意思即可,以後專案開發中用到了還會講解。】,例如:
import json
from decimal import Decimal
from datetime import datetime
data = [
{"id": 1, "name": "武沛齊", "age": 18, 'size': Decimal("18.99"), 'ctime': datetime.now()},
{"id": 2, "name": "alex", "age": 18, 'size': Decimal("9.99"), 'ctime': datetime.now()},
]
class MyJSONEncoder(json.JSONEncoder):
def default(self, o):
if type(o) == Decimal:
return str(o)
elif type(o) == datetime:
return o.strftime("%Y-%M-%d")
return super().default(o)
res = json.dumps(data, cls=MyJSONEncoder)
print(res)
1.1.3 其他功能
json模組中常用的是:
-
json.dumps
,序列化生成一個字串。 -
json.loads
,發序列化生成python資料型別。 -
json.dump
,將資料序列化並寫入檔案(不常用)import json data = [ {"id": 1, "name": "武沛齊", "age": 18}, {"id": 2, "name": "alex", "age": 18}, ] file_object = open('xxx.json', mode='w', encoding='utf-8') json.dump(data, file_object) file_object.close()
-
json.load
,讀取檔案中的資料並反序列化為python的資料型別(不常用)import json file_object = open('xxx.json', mode='r', encoding='utf-8') data = json.load(file_object) print(data) file_object.close()
1.2 時間處理
-
UTC/GMT:世界時間
-
本地時間:本地時區的時間。
Python中關於時間處理的模組有兩個,分別是time和datetime。
1.2.1 time
import time
# 獲取當前時間戳(自1970-1-1 00:00)
v1 = time.time()
print(v1)
# 時區
v2 = time.timezone
# 停止n秒,再執行後續的程式碼。
time.sleep(5)
1.2.2 datetime
在平時開發過程中的時間一般是以為如下三種格式存在:
-
datetime
from datetime import datetime, timezone, timedelta v1 = datetime.now() # 當前本地時間 print(v1) tz = timezone(timedelta(hours=7)) # 當前東7區時間 v2 = datetime.now(tz) print(v2) v3 = datetime.utcnow() # 當前UTC時間 print(v3)
from datetime import datetime, timedelta v1 = datetime.now() print(v1) # 時間的加減 v2 = v1 + timedelta(days=140, minutes=5) print(v2) # datetime型別 + timedelta型別
from datetime import datetime, timezone, timedelta v1 = datetime.now() print(v1) v2 = datetime.utcnow() # 當前UTC時間 print(v2) # datetime之間相減,計算間隔時間(不能相加) data = v1 - v2 print(data.days, data.seconds / 60 / 60, data.microseconds) # datetime型別 - datetime型別 # datetime型別 比較 datetime型別
-
字串
# 字串格式的時間 ---> 轉換為datetime格式時間 text = "2021-11-11" v1 = datetime.strptime(text,'%Y-%m-%d') # %Y 年,%m,月份,%d,天。 print(v1)
# datetime格式 ----> 轉換為字串格式 v1 = datetime.now() val = v1.strftime("%Y-%m-%d %H:%M:%S") print(val)
-
時間戳
# 時間戳格式 --> 轉換為datetime格式 ctime = time.time() # 11213245345.123 v1 = datetime.fromtimestamp(ctime) print(v1)
# datetime格式 ---> 轉換為時間戳格式 v1 = datetime.now() val = v1.timestamp() print(val)
練習題
-
日誌記錄,將使用者輸入的資訊寫入到檔案,檔名格式為
年-月-日-時-分.txt
。from datetime import datetime while True: text = input("請輸入內容:") if text.upper() == "Q": break current_datetime = datetime.now().strftime("%Y-%m-%d-%H-%M") file_name = "{}.txt".format(current_datetime) with open(file_name, mode='a', encoding='utf-8') as file_object: file_object.write(text) file_object.flush()
-
使用者註冊,將使用者資訊寫入Excel,其中包含:使用者名稱、密碼、註冊時間 三列。
import os import hashlib from datetime import datetime from openpyxl import load_workbook from openpyxl import workbook BASE_DIR = os.path.dirname(os.path.abspath(__file__)) FILE_NAME = "db.xlsx" def md5(origin): hash_object = hashlib.md5("sdfsdfsdfsd23sd".encode('utf-8')) hash_object.update(origin.encode('utf-8')) return hash_object.hexdigest() def register(username, password): db_file_path = os.path.join(BASE_DIR, FILE_NAME) if os.path.exists(db_file_path): wb = load_workbook(db_file_path) sheet = wb.worksheets[0] next_row_position = sheet.max_row + 1 else: wb = workbook.Workbook() sheet = wb.worksheets[0] next_row_position = 1 user = sheet.cell(next_row_position, 1) user.value = username pwd = sheet.cell(next_row_position, 2) pwd.value = md5(password) ctime = sheet.cell(next_row_position, 3) ctime.value = datetime.now().strftime("%Y-%m-%d %H:%M:%S") wb.save(db_file_path) def run(): while True: username = input("請輸入使用者名稱:") if username.upper() == "Q": break password = input("請輸入密碼:") register(username, password) if __name__ == '__main__': run()
1.3 正則表示式相關
當給你一大堆文字資訊,讓你提取其中的指定資料時,可以使用正則來實現。例如:提取文字中的郵箱和手機號
import re
text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀"
phone_list = re.findall("1[3|5|8|9]\d{9}", text)
print(phone_list)
1.3.1 正則表示式
1. 字元相關
-
wupeiqi
匹配文字中的wupeiqiimport re text = "你好wupeiqi,阿斯頓發wupeiqasd 阿士大夫能接受的wupeiqiff" data_list = re.findall("wupeiqi", text) print(data_list) # ['wupeiqi', 'wupeiqi'] 可用於計算字串中某個字元出現的次數
-
[abc]
匹配a或b或c 字元。import re text = "你2b好wupeiqi,阿斯頓發awupeiqasd 阿士大夫a能接受的wffbbupqaceiqiff" data_list = re.findall("[abc]", text) print(data_list) # ['b', 'a', 'a', 'a', 'b', 'b', 'c']
import re text = "你2b好wupeiqi,阿斯頓發awupeiqasd 阿士大夫a能接受的wffbbupqcceiqiff" data_list = re.findall("q[abc]", text) print(data_list) # ['qa', 'qc']
-
[^abc]
匹配除了abc意外的其他字元。import re text = "你wffbbupceiqiff" data_list = re.findall("[^abc]", text) print(data_list) # ['你', 'w', 'f', 'f', 'u', 'p', 'e', 'i', 'q', 'i', 'f', 'f']
-
[a-z]
匹配a~z的任意字元( [0-9]也可以 )。import re text = "alexrootrootadmin" data_list = re.findall("t[a-z]", text) print(data_list) # ['tr', 'ta']
-
.
代指除換行符以外的任意字元。import re text = "alexraotrootadmin" data_list = re.findall("r.o", text) print(data_list) # ['rao', 'roo']
import re text = "alexraotrootadmin" data_list = re.findall("r.+o", text) # 貪婪匹配 print(data_list) # ['raotroo']
import re text = "alexraotrootadmin" data_list = re.findall("r.+?o", text) # 非貪婪匹配 print(data_list) # ['rao']
-
\w
代指字母或數字或下劃線(漢字)。import re text = "北京武沛alex齊北 京武沛alex齊" data_list = re.findall("武\w+x", text) print(data_list) # ['武沛alex', '武沛alex']
-
\d
代指數字import re text = "root-ad32min-add3-admd1in" data_list = re.findall("d\d", text) print(data_list) # ['d3', 'd3', 'd1']
import re text = "root-ad32min-add3-admd1in" data_list = re.findall("d\d+", text) print(data_list) # ['d32', 'd3', 'd1']
-
\s
代指任意的空白符,包括空格、製表符等。import re text = "root admin add admin" data_list = re.findall("a\w+\s\w+", text) print(data_list) # ['admin add']
2. 數量相關
-
*
重複0次或更多次import re text = "他是大B個,確實是個大2B。" data_list = re.findall("大2*B", text) print(data_list) # ['大B', '大2B']
-
+
重複1次或更多次import re text = "他是大B個,確實是個大2B,大3B,大66666B。" data_list = re.findall("大\d+B", text) print(data_list) # ['大2B', '大3B', '大66666B']
-
?
重複0次或1次import re text = "他是大B個,確實是個大2B,大3B,大66666B。" data_list = re.findall("大\d?B", text) print(data_list) # ['大B', '大2B', '大3B']
-
{n}
重複n次import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("151312\d{5}", text) print(data_list) # ['15131255789']
-
{n,}
重複n次或更多次import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("\d{9,}", text) print(data_list) # ['442662578', '15131255789']
-
{n,m}
重複n到m次import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("\d{10,15}", text) print(data_list) # ['15131255789']
3. 括號(分組)
-
提取資料區域
import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("15131(2\d{5})", text) print(data_list) # ['255789']
import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來15131266666呀" data_list = re.findall("15(13)1(2\d{5})", text) print(data_list) # [ ('13', '255789') ]
import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("(15131(2\d{5}))", text) print(data_list) # [('15131255789', '255789')]
-
獲取指定區域 + 或條件
import re text = "樓主15131root太牛15131alex逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("15131(2\d{5}|r\w+太)", text) print(data_list) # ['root太', '255789']
import re text = "樓主15131root太牛15131alex逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" data_list = re.findall("(15131(2\d{5}|r\w+太))", text) print(data_list) # [('15131root太', 'root太'), ('15131255789', '255789')]
練習題
-
利用正則匹配QQ號碼
[1-9]\d{4,}
-
身份證號碼
import re text = "dsf130429191912015219k13042919591219521Xkk" data_list = re.findall("\d{17}[\dX]", text) # [abc] print(data_list) # ['130429191912015219', '13042919591219521X']
import re text = "dsf130429191912015219k13042919591219521Xkk" data_list = re.findall("\d{17}(\d|X)", text) print(data_list) # ['9', 'X']
import re text = "dsf130429191912015219k13042919591219521Xkk" data_list = re.findall("(\d{17}(\d|X))", text) print(data_list) # [('130429191912015219', '9'), ('13042919591219521X', 'X')]
import re text = "dsf130429191912015219k13042919591219521Xkk" data_list = re.findall("(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)", text) print(data_list) # [('130429', '1919', '12', '01', '521', '9'), ('130429', '1959', '12', '19', '521', 'X')]
-
手機號
import re text = "我的手機哈是15133377892,你的手機號是1171123啊?" data_list = re.findall("1[3-9]\d{9}", text) print(data_list) # ['15133377892']
-
郵箱地址
import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" email_list = re.findall("\w+@\w+\.\w+",text) print(email_list) # ['[email protected]和xxxxx']
import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" email_list = re.findall("[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+", text, re.ASCII) print(email_list) # ['[email protected]', '[email protected]']
import re text = "樓主太牛逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" email_list = re.findall("\w+@\w+\.\w+", text, re.ASCII) print(email_list) # ['[email protected]', '[email protected]']
import re text = "樓主太牛[email protected]逼了,線上想要 [email protected]和[email protected]謝謝樓主,手機號也可15131255789,搞起來呀" email_list = re.findall("(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)", text, re.ASCII) print(email_list) # [('[email protected]', '-2578', '', ''), ('[email protected]', '', '', '')]
-
補充程式碼,實現獲取頁面上的所有評論(已實現),並提取裡面的郵箱。
# 先安裝兩個模組 pip3 install requests pip3 install beautifulsoup4
import re import requests from bs4 import BeautifulSoup res = requests.get( url="https://www.douban.com/group/topic/79870081/", headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36', } ) bs_object = BeautifulSoup(res.text, "html.parser") comment_object_list = bs_object.find_all("p", attrs={"class": "reply-content"}) for comment_object in comment_object_list: text = comment_object.text print(text) # 請繼續補充程式碼,提取text中的郵箱地址
4. 起始和結束
上述示例中都是去一段文字中提取資料,只要文字中存在即可。
但,如果要求使用者輸入的內容必須是指定的內容開頭和結尾,比就需要用到如下兩個字元。
^
開始$
結束
import re
text = "啊[email protected]我靠"
email_list = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
print(email_list) # []
import re
text = "[email protected]"
email_list = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
print(email_list) # ['[email protected]']
這種一般用於對使用者輸入資料格式的校驗比較多,例如:
import re
text = input("請輸入郵箱:")
email = re.findall("^\w+@\w+.\w+$", text, re.ASCII)
if not email:
print("郵箱格式錯誤")
else:
print(email)
5. 特殊字元
由於正則表示式中 * . \ { } ( )
等都具有特殊的含義,所以如果想要在正則中匹配這種指定的字元,需要轉義,例如:
import re
text = "我是你{5}爸爸"
data = re.findall("你{5}爸", text)
print(data) # []
import re
text = "我是你{5}爸爸"
data = re.findall("你\{5\}爸", text)
print(data)
1.3.2 re模組
python中提供了re模組,可以處理正則表示式並對文字進行處理。
-
findall,獲取匹配到的所有資料
import re text = "dsf130429191912015219k13042919591219521Xkk" data_list = re.findall("(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)", text) print(data_list) # [('130429', '1919', '12', '01', '521', '9'), ('130429', '1959', '12', '19', '521', 'X')]
-
match,從起始位置開始匹配,匹配成功返回一個物件,未匹配成功返回None
import re text = "大小逗2B最逗3B歡樂" data = re.match("逗\dB", text) print(data) # None
import re text = "逗2B最逗3B歡樂" data = re.match("逗\dB", text) if data: content = data.group() # "逗2B" print(content)
-
search,瀏覽整個字串去匹配第一個,未匹配成功返回None
import re text = "大小逗2B最逗3B歡樂" data = re.search("逗\dB", text) if data: print(data.group()) # "逗2B"
-
sub,替換匹配成功的位置
import re text = "逗2B最逗3B歡樂" data = re.sub("\dB", "沙雕", text) print(data) # 逗沙雕最逗沙雕歡樂
import re text = "逗2B最逗3B歡樂" data = re.sub("\dB", "沙雕", text, 1) print(data) # 逗沙雕最逗3B歡樂
-
split,根據匹配成功的位置分割
import re text = "逗2B最逗3B歡樂" data = re.split("\dB", text) print(data) # ['逗', '最逗', '歡樂']
import re text = "逗2B最逗3B歡樂" data = re.split("\dB", text, 1) print(data) # ['逗', '最逗3B歡樂']
-
finditer
import re text = "逗2B最逗3B歡樂" data = re.finditer("\dB", text) for item in data: print(item.group())
import re text = "逗2B最逗3B歡樂" data = re.finditer("(?P<xx>\dB)", text) # 命名分組 for item in data: print(item.groupdict())
text = "dsf130429191912015219k13042919591219521Xkk" data_list = re.finditer("\d{6}(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2})\d{3}[\d|X]", text) for item in data_list: info_dict = item.groupdict() print(info_dict)
小結
到此,關於最常見的內建模組就全部講完了(共11個),現階段只需要掌握這些模組的使用即可,在後續的課程和練習題中也會涉及到一起其他內建模組。
- os
- shutil
- sys
- random
- hashlib
- configparser
- xml
- json
- time
- datetime
- re
2. 專案開發規範
現階段,我們在開發一些程式時(終端執行),應該遵循一些結構的規範,讓你的系統更加專業。
2.1 單檔案應用
當基於python開發簡單應用時(一個py檔案就能搞定),需要注意如下幾點。
"""
檔案註釋
"""
import re
import random
import requests
from openpyxl import load_workbook
DB = "XXX"
def do_something():
""" 函式註釋 """
# TODO 待完成時,下一期實現xxx功能
for i in range(10):
pass
def run():
""" 函式註釋 """
# 對功能程式碼進行註釋
text = input(">>>")
print(text)
if __name__ == '__main__':
run()
2.2 單可執行檔案
新建立一個專案,假設名字叫 【crm】,可以建立如下檔案和資料夾來存放程式碼和資料。
crm
├── app.py 檔案,程式的主檔案(儘量精簡)
├── config.py 檔案,配置檔案(放相關配置資訊,程式碼中讀取配置資訊,如果想要修改配置,即可以在此修改,不用再去程式碼中逐一修改了)
├── db 資料夾,存放資料
├── files 資料夾,存放檔案
├── src 包,業務處理的程式碼
└── utils 包,公共功能
示例程式見附件:crm.zip
2.3 多可執行檔案
新建立專案,假設名稱叫【killer】,可以建立如下檔案和資料夾來存放程式碼和資料。
killer
├── bin 資料夾,存放多個主檔案(可執行)
│ ├── app1.py
│ └── app2.py
├── config 包,配置檔案
│ ├── __init__.py
│ └── settings.py
├── db 資料夾,存放資料
├── files 資料夾,存放檔案
├── src 包,業務程式碼
│ └── __init__.py
└── utils 包,公共功能
└── __init__.py
總結
- json格式和json模組
- json模組處理特殊的資料型別
- datetime格式與字串、時間戳以及相關之間的轉換。
- datetime格式時間與timedelta的加減。
- 兩個datetime相減可以計算時間間隔,得到的是一個timedelta格式的時間。
- 瞭解正則表示式的編寫方式和python中re模組的使用。
- 專案開發規範。
作業:開發短視訊資訊平臺
- 有video.csv視訊庫檔案,其中有999條短視訊資料,格式如下:【 video.csv 檔案已為大家提供好,在day15課件目錄下。 】
-
專案的核心功能有:
-
分頁看新聞(每頁顯示10條),提示使用者輸入頁碼,根據頁碼顯示指定頁面的資料。
- 提示使用者輸入頁碼,根據頁碼顯示指定頁面的資料。
- 當用戶輸入的頁碼不存在時,預設顯示第1頁
-
搜尋專區
- 使用者輸入關鍵字,根據關鍵詞篩選出所有匹配成功的短視訊資訊。
- 支援的搜尋兩種搜尋格式:
id=1715025
,篩選出id等於1715025的視訊(video.csv的第一列)。key=文字
,模糊搜尋,篩選包含關鍵字的所有新聞(video.csv的第二列)。
-
下載專區
-
使用者輸入視訊id,根據id找到對應的mp4視訊下載地址,然後下載視訊到專案的files目錄。
-
視訊的檔名為:
視訊id-年-月-日-時-分-秒.mp4
-
視訊下載程式碼示例
import requests res = requests.get( url='https://video.pearvideo.com/mp4/adshort/20210105/cont-1715046-15562045_adpkg-ad_hd.mp4' ) # 視訊總大小(位元組) file_size = int(res.headers['Content-Length']) download_size = 0 with open('xxx.mp4', mode='wb') as file_object: # 分塊讀取下載的視訊檔案(最多一次讀128位元組),並逐一寫入到檔案中。 len(chunk)表示實際讀取到每塊的視訊檔案大小。 for chunk in res.iter_content(128): download_size += len(chunk) file_object.write(chunk) file_object.flush() message = "視訊總大小為:{}位元組,已下載{}位元組。".format(file_size, download_size) print(message) file_object.close() res.close()
-
下載的過程中,輸出已下載的百分比,示例程式碼如下:
import time print("正在下載中...") for i in range(101): text = "\r{}%".format(i) print(text, end="") time.sleep(0.2) print("\n下載完成")
-
-
-
附贈
自動採集梨視訊1000條資訊的爬蟲指令碼。梨視訊平臺系統更新後可能會導致下載失敗,到時候需根據平臺調整再來修改程式碼。
"""
下載梨視訊的:視訊ID,視訊標題,視訊URL地址 並寫入到本次 video.csv 檔案中。
執行此指令碼需要預先安裝:
pip install request
pip install beautifulsoup4
"""
import requests
from bs4 import BeautifulSoup
def get_mp4_url(video_id):
data = requests.get(
url="https://www.pearvideo.com/videoStatus.jsp?contId={}".format(video_id),
headers={
"Referer": "https://www.pearvideo.com/video_{}".format(video_id),
}
)
response = data.json()
image_url = response['videoInfo']['video_image']
video_url = response['videoInfo']['videos']['srcUrl']
middle = image_url.rsplit('/', 1)[-1].rsplit('-', 1)[0]
before, after = video_url.rsplit('/', 1)
suffix = after.split('-', 1)[-1]
url = "{}/{}-{}".format(before, middle, suffix)
return url
def download_video():
file_object = open('video.csv', mode='w', encoding='utf-8')
count = 0
while count <= 999:
res = requests.get(
url="https://www.pearvideo.com/category_loading.jsp?reqType=14&categoryId=&start={}".format(count)
)
bs = BeautifulSoup(res.text, 'lxml')
a_list = bs.find_all("a", attrs={'class': "vervideo-lilink"})
for tag in a_list:
title = tag.find('div', attrs={'class': "vervideo-title"}).text.strip()
video_id = tag.get('href').split('_')[-1]
mp4_url = get_mp4_url(video_id)
row = "{},{},{}\n".format(video_id, title, mp4_url)
file_object.write(row)
file_object.flush()
count += 1
message = "已下載{}個".format(count)
print(message)
file_object.close()
if __name__ == '__main__':
download_video()