背景:上交学子肯定都用过好大学在线的慕课,可是老师上课的PPT课件只能在网页端预览,并不提供下载,这是非常蛋疼的一件事,毕竟上交午夜就断网啊……
好了话不多说,这回以本人的专业课为例,记录下如何批量爬下一门课程的所有课件。
首先我们分析下解决的思路:
- 模拟登录
- 分析网页,找到PPT的链接
- 利用python解析网页,把所有PPT链接保存下来
- 下载PPT
大概就是这样,模拟登录这里为了省事,我直接在网页端登录好,然后用chrome拿到cookie就能直接访问了。
import requests
import re
from bs4 import BeautifulSoup
headers = {"User-Agent": 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest'}
# 这是我课程的导航页,所有章节都可以在这看到
nav_page = 'https://cnmooc.org/portal/session/unitNavigation/10036.mooc'
#这是从chrome中拿到的登录后的cookie
cookie = 'moocvk=a9628796e8c3450a85791954be220ee6; sos=true; moocsk=f3f8b5550828439c932b0fe033d74c29; JSESSIONID=225C396119183B79BE506D97B9AAC5F2.tomcat-host1-1; Hm_lvt_ed399044071fc36c6b711fa9d81c2d1c=1539508316,1539508326,1539579539,1539589878; Hm_lpvt_ed399044071fc36c6b711fa9d81c2d1c=1539589908; BEC=f6c42c24d0c76e7acea242791ab87e34|1539592046|1539579539'
# 这个函数把上面这个cookie字符串转化为python字典
def extract_cookies(cookie):
"""从浏览器或者request headers中拿到cookie字符串,提取为字典格式的cookies"""
cookies = dict([l.split("=", 1) for l in cookie.split("; ")])
return cookies
好,第一步over,第二步也很简单。随便打开一个章节PPT的网页页面,然后f12打开开发者工具,在element标签下搜索ppt
这个关键词…直到我发现
/repositry/resource/d/1703/27/0cced6dba98d4e5a9977d7b83da3bb04.pptx
这一串,我知道我成功了!把完整的地址输入chrome,果然不用登录都可以直接下载了。
再来第三步,把这些ppt的地址都存下来。显然这是经过加密的,找不到规律啊,所以只能一个个爬。这并不麻烦啊,每个PPT的id都在导航页。
def get_all_links(cookies):
s = requests.session()
r = s.get(nav_page, headers=headers, cookies=cookies)
html = r.text
soup = BeautifulSoup(html)
# lecture-action linkPlay 是ppt对应的class, 下面这行找到ppt所在的a标签,我们同时存下id和ppt的名字,后面就好给文件命名了。
a = soup.find_all('a', "lecture-action linkPlay", title=re.compile("pptx"))
itemid = []
titles = []
for item in a:
itemid.append(item['itemid'])
titles.append(item['title'])
return itemid, titles
这一步只是拿到ppt所在网页的id,也就相当于ppt页面的网址。那么ppt资源的地址其实还没拿到。我开始以为就在这个页面里,后来发现并不是,那个资源地址其实在一段js代码内。于是,在开发者工具的network标签下继续搜索ppt,找到这个ppt资源的地址其实是在https://cnmooc.org/study/play.mooc
这个页面下的,并且该页面用的是post方式提交,注意同时还要提交一个表单。代码如下:
def get_resource_links(cookies, unitid):
url = 'https://cnmooc.org/study/play.mooc'
base = 'https://cnmooc.org'
res_links = []
for id in unitid:
data = {'itemId': id, 'itemType': '20', 'testPaperId':''}
s = requests.session()
r = s.post(url, data, cookies=cookies)
try:
res_links.append(base + re.search('/repositry/.*\.pptx',r.text).group())
except AttributeError:
print("not found")
return res_links
这样其实就拿到所有资源的地址了,最后一步很简单就是下载啦,随便百度了一下,就有源码:
def save_files():
for i in range(0, len(res_links)):
html = requests.get(res_links[i], headers=headers)
with open(titles[i], 'wb') as file:
file.write(html.content)
save_files()
省略了部分代码,大意就是这样。具体的情况还是要具体分析。其中我入了不少坑也不多说了,重点要细心一点,提交请求的时候有的需要cookie,有的还需要表单,这些在开发者工具里分析的时候细心点,多尝试,肯定能成功的……
网友评论