慕课网免费教程爬虫

1. 爬虫背景

刚开始学Python的时候,在慕课网上看到了好多Python的教程,有视频的,有文档的。当时网上有一个Java版的教程下载器,有一个缺点,只能下载视频,不能下载文档类的视频。文档类的教程一个一个复制下来粘贴到word上面保存很痛苦的。后来自己想了一下,干嘛不自己写一个爬虫爬取慕课网呢,然后就写了这个爬虫。

2. 前期准备

  • 安装pdfkit
  • 安装wkhtmltopdf
  • 验证安装是否成功


    慕课网免费教程爬虫_第1张图片
    正确显示版本号,说明安装成功

3. 使用的工具

  • Chrome的F12
  • Anaconda
  • Visual Studio Code
  • 运行环境Deepin15.4

4. 爬虫代码

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的内容
    content = requests.get(url)
    return content.text


# 获取课程列表
# i=1
print('增强版慕课网教程爬虫,支持下载非视频类的教程,保存称PDF文件')
print('输入课程编号,如http://www.imooc.com/learn/177,输入177即可')
while True:
    # 获取课程的内容
    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())
        # 根据课程名称建立一个文件夹
        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()
        # 简单处理一下保存文件的文件名,文件名不能有\/?<>""
        # 所有先将这些字符替换掉,否则保存成文件的时候会出错
        if '/' in file_name:
            file_name = course_name.get_text().strip().replace('/', '&')
        if '\"' in file_name:
            file_name = course_name.get_text().strip().replace('\"', '“')
        # 将课程的名称及学习地址保存程一个文件
        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()函数分割字符串,默认使用空格、换行符、制表符分割,并返回一个列表(列表最后一个元素不需要)
                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()函数将列表转换成String
                if "video" in class_link['href']:
                    # 用于统计课程有几个视频
                    video_count = video_count + 1
                # 用于统计课程有几个学习内容(有的课程不是视频教程)
                item_count = item_count + 1
        print('共' + str(video_count) + '个视频')
        print('共' + str(item_count) + '个学习内容', '\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 = {
                    # 定义编码类型,防止中文出现乱码
                    'encoding': "UTF-8"
                }
                # windows环境下制定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:
                # 简单的文件名的合法性检查
                video_name = temp.split('>')[0].replace(':', ':')
                video_link = temp.split('>')[1]
                video_id = video_link.split(
                    '/')[len(video_link.split('/')) - 1]
                # 获取视频下载地址,返回一个json数据
                url = "http://www.imooc.com/course/ajaxmediainfo/?mid={}&mode=flash".format(
                    video_id.strip())
                # 返回的是一个json字符串
                video_info = get_url_content(url)
                # print('video_info', video_info)
                video_link = json.loads(video_info)
                '''Json数据格式
                    {
                        "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集成环境下载和安装",
                                "time": 0,
                                "practise": []
                            }
                        },
                        "msg": "成功"
                    }
                    '''
                print(video_link['data']['result']['name'], '下载中...')
                # 下载视频,默认下载高清视频
                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('没有这个课程,请输入正确的编号···')

5. 项目说明

  • 项目地址:慕课网免费教程下载器
  • 后续任务:代码比较乱,后面准备用Scrapy重新写一次,实现输入要爬取的关键字,自动爬取跟关键字相关的教程,包括分页爬取。

6. 爬取的教程分享

因为看到(1组)学习视频推荐--编程语言基础文章里面有这两个教程,所以就直接爬取了这两个课程上传到百度云盘,方便有需要的人下载。

  • Python入门
  • Python进阶

你可能感兴趣的:(慕课网免费教程爬虫)