1. 爬蟲(chóng)背景
剛開(kāi)始學(xué)Python的時(shí)候,在慕課網(wǎng)上看到了好多Python的教程慕的,有視頻的阎肝,有文檔的。當(dāng)時(shí)網(wǎng)上有一個(gè)Java版的教程下載器肮街,有一個(gè)缺點(diǎn)风题,只能下載視頻,不能下載文檔類的視頻嫉父。文檔類的教程一個(gè)一個(gè)復(fù)制下來(lái)粘貼到word上面保存很痛苦的沛硅。后來(lái)自己想了一下,干嘛不自己寫一個(gè)爬蟲(chóng)爬取慕課網(wǎng)呢绕辖,然后就寫了這個(gè)爬蟲(chóng)摇肌。
2. 前期準(zhǔn)備
- 安裝pdfkit
- 安裝wkhtmltopdf
-
驗(yàn)證安裝是否成功
3. 使用的工具
- Chrome的F12
- Anaconda
- Visual Studio Code
- 運(yùn)行環(huán)境Deepin15.4
4. 爬蟲(chóng)代碼
from bs4 import BeautifulSoup
from urllib.request import urlopen
import urllib.request
from urllib.error import URLError, HTTPError
import json
import re
import requests
import os
import pdfkit
def get_url_content(url):
# 獲取url的內(nèi)容
content = requests.get(url)
return content.text
# 獲取課程列表
# i=1
print('增強(qiáng)版慕課網(wǎng)教程爬蟲(chóng)仪际,支持下載非視頻類的教程围小,保存稱PDF文件')
print('輸入課程編號(hào),如http://www.imooc.com/learn/177弟头,輸入177即可')
while True:
# 獲取課程的內(nèi)容
chapter_address = input('輸入課程地址(輸入exit退出):')
if(chapter_address == 'exit'):
break
course_url = "http://www.imooc.com/learn/" + chapter_address.strip()
try:
soup = BeautifulSoup(get_url_content(course_url), "html.parser")
video_count = 0
item_count = 0
# 獲取課程名稱
course_name = soup.find('div', class_="hd clearfix")
print(course_name.get_text())
# 根據(jù)課程名稱建立一個(gè)文件夾
video_path = os.path.abspath(
'.') + '/' + course_name.get_text().strip() + '/'
if not os.path.isdir(video_path):
os.mkdir(video_path)
file_name = course_name.get_text().strip()
# 簡(jiǎn)單處理一下保存文件的文件名吩抓,文件名不能有\(zhòng)/?<>""
# 所有先將這些字符替換掉,否則保存成文件的時(shí)候會(huì)出錯(cuò)
if '/' in file_name:
file_name = course_name.get_text().strip().replace('/', '&')
if '\"' in file_name:
file_name = course_name.get_text().strip().replace('\"', '“')
# 將課程的名稱及學(xué)習(xí)地址保存程一個(gè)文件
output_file = open(video_path + file_name + '.txt', 'w')
chapter_names = soup.find_all('div', class_="chapter")
for chapter_name in chapter_names:
output_file.write(chapter_name.find('strong').get_text().split()[
0] + ' ' + chapter_name.find('strong').get_text().split()[1] + '\r\n')
class_links = chapter_name.find_all(
'a', href=re.compile(r"\d"), class_="J-media-item")
for class_link in class_links:
# 使用split()函數(shù)分割字符串赴恨,默認(rèn)使用空格疹娶、換行符、制表符分割伦连,并返回一個(gè)列表(列表最后一個(gè)元素不需要)
output_file.write(' '.join(class_link.get_text().strip().split()[0:len(class_link.get_text().strip(
).split()) - 1]) + '>' + 'http://www.imooc.com' + class_link['href'] + '\r\n') # join()函數(shù)將列表轉(zhuǎn)換成String
if "video" in class_link['href']:
# 用于統(tǒng)計(jì)課程有幾個(gè)視頻
video_count = video_count + 1
# 用于統(tǒng)計(jì)課程有幾個(gè)學(xué)習(xí)內(nèi)容(有的課程不是視頻教程)
item_count = item_count + 1
print('共' + str(video_count) + '個(gè)視頻')
print('共' + str(item_count) + '個(gè)學(xué)習(xí)內(nèi)容', '\r\n\r\n')
output_file.close()
video_info_file = open(video_path + file_name + '.txt', 'r')
info_data = video_info_file.readlines()
for temp in info_data:
# 保存文檔教程雨饺,生成pdf
if 'code' in temp:
file_name = temp.split('>')[0].replace(':', ':')
code_link = temp.split('>')[1]
code_content = BeautifulSoup(urllib.request.urlopen(
code_link).read().decode('utf-8'), "html.parser")
code_content.find('div', class_="code-panel")
options = {
# 定義編碼類型钳垮,防止中文出現(xiàn)亂碼
'encoding': "UTF-8"
}
# windows環(huán)境下制定wkhtmltopdf的路徑
# config = pdfkit.configuration(
# wkhtmltopdf=r'C:\Program Files (x86)\wkhtmltopdf\bin\wkhtmltopdf.exe')
# pdfkit.from_string(
# str(code_content.find('div',class_="code-panel")), file_name
# +'.pdf', options=options, configuration=config)
print(file_name, '下載中...')
# pdfkit生成PDF文檔保存
pdfkit.from_string(
str(code_content.find('div', class_="code-panel")), video_path + file_name + '.pdf', options=options)
elif 'video' in temp:
# 簡(jiǎn)單的文件名的合法性檢查
video_name = temp.split('>')[0].replace(':', ':')
video_link = temp.split('>')[1]
video_id = video_link.split(
'/')[len(video_link.split('/')) - 1]
# 獲取視頻下載地址,返回一個(gè)json數(shù)據(jù)
url = "http://www.imooc.com/course/ajaxmediainfo/?mid={}&mode=flash".format(
video_id.strip())
# 返回的是一個(gè)json字符串
video_info = get_url_content(url)
# print('video_info', video_info)
video_link = json.loads(video_info)
'''Json數(shù)據(jù)格式
{
"result": 0,
"data": {
"result": {
"mid": 3510,
"mpath": [
"http://v2.mukewang.com/d51dbce1-b075-4558-b1b3-bfb4fcc5ee0a/L.mp4?auth_key=1480781145-0-0-32089e0973914437dc19596d2cc552c8",
"http://v2.mukewang.com/d51dbce1-b075-4558-b1b3-bfb4fcc5ee0a/M.mp4?auth_key=1480781145-0-0-4d0a14128facb64e0f94bba9419ce7a4",
"http://v2.mukewang.com/d51dbce1-b075-4558-b1b3-bfb4fcc5ee0a/H.mp4?auth_key=1480781145-0-0-68c1c5dbdd7540020065c030842843d8"
],
"cpid": "918",
"name": "WAMPServer集成環(huán)境下載和安裝",
"time": 0,
"practise": []
}
},
"msg": "成功"
}
'''
print(video_link['data']['result']['name'], '下載中...')
# 下載視頻额港,默認(rèn)下載高清視頻
urllib.request.urlretrieve(video_link['data']['result']['mpath'][-1],
video_path + video_name.split()[0] + ' ' + video_link['data']['result']['name'] + '.mp4')
# input_file.close()
else:
pass
except HTTPError as e:
print('沒(méi)有這個(gè)課程饺窿,請(qǐng)輸入正確的編號(hào)···')
5. 項(xiàng)目說(shuō)明
- 項(xiàng)目地址:慕課網(wǎng)免費(fèi)教程下載器
- 后續(xù)任務(wù):代碼比較亂,后面準(zhǔn)備用Scrapy重新寫一次移斩,實(shí)現(xiàn)輸入要爬取的關(guān)鍵字肚医,自動(dòng)爬取跟關(guān)鍵字相關(guān)的教程,包括分頁(yè)爬取向瓷。
6. 爬取的教程分享
因?yàn)榭吹?a href="http://www.reibang.com/p/5fc6ab5de253" target="_blank">(1組)學(xué)習(xí)視頻推薦--編程語(yǔ)言基礎(chǔ)文章里面有這兩個(gè)教程肠套,所以就直接爬取了這兩個(gè)課程上傳到百度云盤,方便有需要的人下載猖任。