本文的全部代碼都在GitHub上託管,想要代碼的同窗請點擊這裏😸html
序:因爲本身想要實現一個課程推薦系統,須要在各大視頻網站上爬取全部視頻課程,從而爲後續的推薦工做提供大量數據,在此篇博客中我分別爬取了MOOC、網易雲課堂、騰訊課堂、學堂在線共約15萬條數據。python
運行環境:mysql
mysqlclient
~=1.4.6git
requests
~=2.22.0程序員
bs4
~=0.0.1github
beautifulsoup4
~=4.8.2web
首先進入網站,在這裏咱們分析他的API設計,先要找到他是從哪個API得到相應課程的,通過分析以後咱們發現是https://www.icourse163.org/web/j/courseBean.getCoursePanelListByFrontCategory.rpc
這個API,其返回內容以下:
算法
而後咱們隨意點擊頁面上的一個課程,找到其課程url的規律,打開溝通心理學這門課程,其URL是https://www.icourse163.org/course/HIT-1001515007
,而溝通心理學這門課程返回的信息是:sql
// 在這裏我只保留了我須要的一些數據 { 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的狀況,也算是省了很多事😂。在這裏把代碼與思路分享給你們,但願可以給到你們一些幫助。全部代碼請點擊這裏😸