教你爬取騰訊課堂、網易雲課堂、mooc等所有課程資訊

Jacob是我了發表於2020-04-17

本文的所有程式碼都在GitHub上託管,想要程式碼的同學請點選這裡?

:由於自己想要實現一個課程推薦系統,需要在各大視訊網站上爬取所有視訊課程,從而為後續的推薦工作提供大量資料,在此篇部落格中我分別爬取了MOOC、網易雲課堂、騰訊課堂、學堂線上共約15萬條資料。

執行環境

  1. mysqlclient~=1.4.6

  2. requests~=2.22.0

  3. bs4~=0.0.1

  4. beautifulsoup4~=4.8.2

MOOC

首先進入網站,在這裡我們分析他的API設計,先要找到他是從哪一個API獲得相應課程的,經過分析之後我們發現是https://www.icourse163.org/web/j/courseBean.getCoursePanelListByFrontCategory.rpc這個API,其返回內容如下:

然後我們隨意點選頁面上的一個課程,找到其課程url的規律,開啟溝通心理學這門課程,其URL是https://www.icourse163.org/course/HIT-1001515007,而溝通心理學這門課程返回的資訊是:

// 在這裡我只保留了我需要的一些資料
{
    name: "溝通心理學",
    id: 1001515007,
    schoolPanel: {id: 9005, name: "哈爾濱工業大學", shortName: "HIT"}
}

我們可以發現課程的URL就是學校的簡稱-id,這樣就可以組成課程URL,現在我們得知課程URL如何得知,那麼這些課程資料需要傳什麼引數呢,如下:

{
    categoryId: -1, // 類別id,因為我這裡選的全部,所以是-1
    type: 30,
    orderBy: 0,
    pageIndex: 1, // 第幾頁
    pageSize: 20 // 每頁多少條資料
}

到這裡就新產生了一個問題,categoryId是怎麼來的,我們繼續看網頁請求的api列表,找到這樣一個APIhttps://www.icourse163.org/web/j/mocCourseCategoryBean.getCategByType.rpc,其返回結果如下:

資料結構大致如下:

我們想要得到的課程分類特別細緻的話就需要一直向下找json的children,直到children為空,演算法的話就採用遞迴演算法就可以。

到現在為止我們已經知道了如何獲取類別id,如果由類別id獲得課程資料,接下來我們就需要把獲取到的資料儲存到資料庫中,我的資料庫包含類別、課程名稱、課程圖片URL、課程URL、課程來源這四個欄位,儲存程式碼如下:

# 儲存到資料庫
def save_to_mysql(data, category_name):
    sql = "insert into webCourses (category, name, site, imgUrl, resource) values ('{0}', '{1}', '{2}', '{3}', '{4}')".format(
        category_name, data["name"],
        'https://www.icourse163.org/course/' + str(data["schoolPanel"]["shortName"]) + "-" + str(data["id"]),
        data["imgUrl"], "慕課")
    print(sql)
    execute(sql)

要注意這裡的execute函式是我封裝的一個函式,具體的作用就是執行sql語句,全部程式碼請到我的GitHub檢視。

騰訊課堂

其實如果你看過了上面MOOC的獲取所有課程的API設計,其他課程網站的API設計也是大致相同的,首先我們要獲得類別id,然後再根據類別id去請求資料,與mooc不同的是騰訊課堂請求課程資料是通過beautifulsoup4解析html內容實現的。下面就來簡單說一下:

獲取課程類別的API:https://ke.qq.com/cgi-bin/get_cat_info

根據類別id獲得資料的網頁url: https://ke.qq.com/course/list?mt=1001&st=2001&tt=3001&page=2,這裡的mt、st、tt分別是三個類別,st是mt的一個子類,tt是st的一個子類,page就是頁數了。

得到的網站如下:

在這裡我們需要的是每一個課程,其實思路很簡單,按F12開啟開發者工具,找到課程對應的dom塊,用beautifulsoup4解析html內容,得到課程陣列就可以了,程式碼如下:

# 獲取課程資料
def get_course_data(mt, st, tt, page, category):
    url = "https://ke.qq.com/course/list?mt=" + str(mt) + "&st=" + str(st) + "&tt=" + str(tt) + "&page=" + str(page)
    response = requests.request("GET", url).text
    bs = BeautifulSoup(response)
    course_blocks = bs.find_all(name='li', attrs={"class": "course-card-item--v3 js-course-card-item"})
    # print(course_blocks)
    if len(course_blocks) != 0:
        for i in range(len(course_blocks)):
            bs = course_blocks[i]
            img = bs.find(name="img", attrs={"class", "item-img"})
            a = bs.find(name="a", attrs={"class", "item-img-link"})
            save_to_mysql(img.attrs["alt"], a.attrs["href"], img.attrs["src"], category)
        return True  # 這裡是返回該類別的下一頁是否還有資料
    else:
        return False

得到資料之後再將這些資料存入到資料庫中就可以了。

網易雲課堂

其實網易雲課堂就和MOOC的API設計非常類似了,畢竟都是網易公司的程式設計師寫的,規範也都差不多,看懂MOOC的api設計的同學直接去我的github看程式碼就可以了。

學堂線上

學堂線上的API設計就比較簡單,直接通過一個API就可以獲得所有的資料,https://next.xuetangx.com/api/v1/lms/get_product_list/?page=1,返回的資料格式如下:

在這裡一個API裡面課程名稱、分類、課程封面URL,課程id可以看的非常請求,下面我們就需要得到課程資訊與課程url之間的關係,我們隨意點開一個課程,分析他的URL,我們就可以發現,課程URL就是https://next.xuetangx.com/course/加上課程的course_sign組成的。

到這裡就分析結束,儲存到資料庫即可。

小結

從上述的分析我們可以看出,各大課程網站的api設計都是類似的,並且他們都沒有做api請求限制,所以我在爬取過程中沒有遇到過被封IP的情況,也算是省了不少事?。在這裡把程式碼與思路分享給大家,希望能夠給到大家一些幫助。所有程式碼請點選這裡?

相關文章