网站调用新浪微博内容(Coursera去一个文件的下载,只有傻子才那么干! )
优采云 发布时间: 2022-01-19 18:08网站调用新浪微博内容(Coursera去一个文件的下载,只有傻子才那么干!
)
首先按照文章的思路,自己试了一下,可以成功
有时候我们需要采集一些经典的东西,时不时回味一下,Coursera上的一些课程无疑是经典。Coursera中完成的大部分课程都提供了完整的配套教学资源,包括ppt、视频和字幕等,离线后学习起来非常容易。很明显,我们不是逐个文件下载的,只有傻子才会这样做,程序员是聪明人!
那么我们聪明的人会怎么做呢?当然,写个脚本批量下载。首先我们需要分析一下手动下载的过程:登录我们的Coursera账号(有些课程需要我们登录并选择一门课程才能看到对应的资源),在课程资源页面找到对应的文件链接,然后使用喜欢的工具下载。
很简单,对吧?我们可以用程序来模仿上面的步骤,这样我们就可以解放双手了。整个程序可以分为三个部分:
登录 Coursera;在课程资源页面上找到资源链接;根据资源链接选择合适的工具下载资源。
让我们详细实现以下内容!
登录
一开始没有加登录模块,以为访问者可以下载相应的课程资源。后来在测试comnetworks-002课程时,发现访问者在访问资源页面时会自动跳转到登录界面。下图显示chrome是隐身的。访问本课程的资源页面时的模式。
模拟登录,我们先找到登录页面,然后使用谷歌的开发者工具分析账号密码是如何上传到服务器的。
我们在登录页面的表格中填写账号密码,然后点击登录。同时,我们需要关注Developer Tools-Network,找到提交账号信息的url。一般情况下,如果要向服务器提交信息,一般采用post方式。这里我们只需要先找到 Method 为 post 的 url。可悲的是,每次登录我的账户,提交账户信息的地址在网络中都找不到。猜到登录成功后,直接跳转到登录成功后的页面,你要找的内容一闪而过。
于是我只输入了一组账号密码,故意登录失败。果然找到了帖子的页面地址,如下图:
地址是: 。为了知道已经向服务器提交了哪些内容,进一步观察post页面中表单的内容,如下图:
我们看到总共有三个字段:
接下来,我们来写吧。我选择使用python的Requests库来模拟登录。这是Requests官网介绍的。
Requests 是一个优雅而简单的 Python HTTP 库,专为人类构建。
其实request使用起来真的很简单方便,这要归功于专门为人类设计的http库。requests 提供了一个 Session 对象,可以用来在不同的请求中传递一些相同的数据,比如在每个请求中携带 cookie。
初步代码如下:
signin_url = "https://accounts.coursera.org/api/v1/login"
logininfo = {"email": "...",
"password": "...",
"webrequest": "true"
}
user_agent = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/36.0.1985.143 Safari/537.36")
post_headers = {"User-Agent": user_agent,
"Referer": "https://accounts.coursera.org/signin"
}
coursera_session = requests.Session()
login_res = coursera_session.post(signin_url,
data=logininfo,
headers=post_headers,
)
if login_res.status_code == 200:
print "Login Successfully!"
else:
print login_res.text
将表单中提交的内容存储在字典中,然后作为数据参数传递给 Session.post 函数。一般情况下最好加上User-Agent、Referer等请求头,User-Agent用来模拟浏览器请求,Referer用来告诉服务器我是从referer页面跳转到请求的页。有时服务器会检查请求的Referer字段,以确保当前请求页面是从固定地址跳转的。
运行上述代码段的结果很奇怪,显示以下消息:Invalid CSRF Token。后来在github上搜索了一个Coursera的批量下载脚本,发现当人们发送页面请求时,headers多了四个字段:XCSRF2Cookie、XCSRF2Token、XCSRFToken、cookie。于是又查看了post页面的请求头,发现确实有这些字段,估计是服务端用来做一些限制的。
用浏览器登录几次后发现XCSRF2Token,XCSRFToken是一个长度为24的随机字符串,而XCSRF2Cookie是“csrf2_token_”加上一个长度为8的随机字符串。但是一直没弄清楚cookie是怎么获取的,但是查看github上的代码,cookie似乎只是“csrftoken”和其他三个的组合。我试过了,它奏效了。
将以下部分添加到原创代码中就足够了。
def randomString(length):
return ''.join(random.choice(string.letters + string.digits) for i in xrange(length))
XCSRF2Cookie = 'csrf2_token_%s' % ''.join(randomString(8))
XCSRF2Token = ''.join(randomString(24))
XCSRFToken = ''.join(randomString(24))
cookie = "csrftoken=%s; %s=%s" % (XCSRFToken, XCSRF2Cookie, XCSRF2Token)
post_headers = {"User-Agent": user_agent,
"Referer": "https://accounts.coursera.org/signin",
"X-Requested-With": "XMLHttpRequest",
"X-CSRF2-Cookie": XCSRF2Cookie,
"X-CSRF2-Token": XCSRF2Token,
"X-CSRFToken": XCSRFToken,
"Cookie": cookie
}
至此,登录功能已经初步实现。
分析资源链接
登录成功后,我们只需要获取资源页面的内容,然后过滤掉我们需要的资源链接即可。资源页面的地址很简单,name就是课程名称。例如,对于课程 comnetworks-002,资源页面地址为 .
抓取到页面资源后,我们需要分析html文件,这里我们选择使用BeautifulSoup。BeautifulSoup 是一个强大的 Python 库,可以从 HTML 或 XML 文件中提取数据。具体使用官网有非常详细的文档,这里不再赘述。在使用 BeautifulSoup 之前,我们必须找出资源链接的规律,以便进行过滤。
课程每周总话题在class=course-item-list-header的div标签下,每周课程在class=course-item-list-section-list的ul标签下,每门课程是在 li 标签下,课程资源位于 li 标签中的 div 标签中。
看了几门课程,发现过滤资源链接的方法很简单,如下:
ppt和ppt资源:使用正则表达式匹配链接;字幕资源:找到title="Subtitles (srt)" 的标签,取其href属性;视频资源:找到 title="Video (MP4)" 的标签,取其 href 属性。
字幕和视频也可以使用正则表达式进行过滤,但使用 BeautifulSoup 根据标题属性进行匹配,以获得更好的可读性。但是ppt和pdf资源没有固定的title属性,所以必须使用正则表达式来匹配。
具体代码如下:
soup = BeautifulSoup(content)
chapter_list = soup.find_all("div", class_="course-item-list-header")
lecture_resource_list = soup.find_all("ul", class_="course-item-list-section-list")
ppt_pattern = re.compile(r'https://[^"]*\.ppt[x]?')
pdf_pattern = re.compile(r'https://[^"]*\.pdf')
for lecture_item, chapter_item in zip(lecture_resource_list, chapter_list):
# weekly title
chapter = chapter_item.h3.text.lstrip()
for lecture in lecture_item:
lecture_name = lecture.a.string.lstrip()
# get resource link
ppt_tag = lecture.find(href=ppt_pattern)
pdf_tag = lecture.find(href=pdf_pattern)
srt_tag = lecture.find(title="Subtitles (srt)")
mp4_tag = lecture.find(title="Video (MP4)")
print ppt_tag["href"], pdf_tag["href"]
print srt_tag["href"], mp4_tag["href"]
下载资源
既然已经获取了资源链接,下载部分就很容易了,这里我选择使用curl来下载。具体思路很简单,就是将curl resource_link -o file_name 输出到一个*敏*感*词*文件,比如feed.sh。这样,你只需要赋予torrent文件执行权限,然后运行torrent文件即可。
为了方便对课程资源进行分类,可以为课程每周的标题创建一个文件夹,然后该周的所有课程都会下载到这个目录中。为了方便我们快速定位到每个类的所有资源,可以将一个类的所有资源文件命名为类名.文件类型。具体实现比较简单,这里不再给出具体方案。您可以查看测试示例中的 feed.sh 文件。部分内容如下:
mkdir 'Week 1: Introduction, Protocols, and Layering'
cd 'Week 1: Introduction, Protocols, and Layering'
curl https://d396qusza40orc.cloudfront.net/comnetworks/lect/1-readings.pdf -o '1-1 Goals and Motivation (15:46).pdf'
curl https://class.coursera.org/comnetworks-002/lecture/subtitles?q=25_en&format=srt -o '1-1 Goals and Motivation (15:46).srt'
curl https://class.coursera.org/comnetworks-002/lecture/download.mp4?lecture_id=25 -o '1-1 Goals and Motivation (15:46).mp4'
curl https://d396qusza40orc.cloudfront.net/comnetworks/lect/1-readings.pdf -o '1-2 Uses of Networks (17:12).pdf'
curl https://class.coursera.org/comnetworks-002/lecture/subtitles?q=11_en&format=srt -o '1-2 Uses of Networks (17:12).srt'
curl https://class.coursera.org/comnetworks-002/lecture/download.mp4?lecture_id=11 -o '1-2 Uses of Networks (17:12).mp4'
至此,我们已经成功完成爬取Coursera课程资源的目标,具体代码放在gist上。使用时,我们只需要运行程序,将课程名称作为参数传递给程序即可(这里的课程名称不是整个课程的全称,而是课程介绍页面地址中的缩写名称,如作为Computer Networks这个类,类名是comnetworks-002)。
后来发现Coursera为我们提供了下载资源的接口。
更新:2014 年 9 月 3 日
其实这个程序可以看成是一个简单的爬虫小程序。下面简单介绍爬虫的概念。
不是一个简单的爬虫
关于什么是爬虫,这就是 wiki 所说的
Web 爬虫是一种 Internet 机器人,它系统地浏览万维网,通常用于 Web 索引。
爬虫整体架构如下(图片来自wiki):
简单来说就是爬虫从Scheduler中获取初始url,下载对应的页面,存储有用的数据,同时分析页面中的链接。
当然,有一些协议可以约束爬虫的行为。比如很多网站都有一个robots.txt文件来指定网站哪些内容可以爬取,哪些不能爬取。
每个搜索引擎的背后都有一个强大的爬虫程序,它的触角延伸到网络的各个角落,不断采集有用的信息并建立索引。这种搜索引擎级别的爬虫实现起来非常复杂,因为互联网上的页面数量太多,仅仅遍历它们是非常困难的,更不用说分析页面信息和建立索引了。
在实际应用中,我们只需要爬取特定站点,爬取少量资源,实现起来要简单得多。但是,仍然有很多令人头疼的问题。例如,许多页面元素是由 javascript 生成的。这时候,我们需要一个javascript引擎来渲染整个页面,然后进行过滤。
雪上加霜的是,很多网站为了防止爬虫爬取资源采取了一些措施,比如在一段时间内限制对同一IP的访问次数,或者限制两次操作的时间间隔,添加验证码等等. 在大多数情况下,我们不知道如何在服务器端阻止爬虫,所以要让爬虫工作起来确实很困难。
参考:
github:coursera-dl/coursera
github:coursera-下载器
python抓取页面元素失败
维基:网络爬虫
如何开始使用 Python 爬虫?
补充:上述过程中用到的python requests 模块的下载地址如下:
requests模块文章的详细介绍如下:
测试后完整代码如下:
import requests
import random
import string
signin_url = "https://accounts.coursera.org/api/v1/login"
logininfo = {"email": "已注册邮箱",
"password": "密码",
"webrequest": "true"
}
user_agent = ("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)")
def randomString(length):
return ''.join(random.choice(string.letters + string.digits) for i in xrange(length))
XCSRF2Cookie = 'csrf2_token_%s' % ''.join(randomString(8))
XCSRF2Token = ''.join(randomString(24))
XCSRFToken = ''.join(randomString(24))
cookie = "csrftoken=%s; %s=%s" % (XCSRFToken, XCSRF2Cookie, XCSRF2Token)
post_headers = {"User-Agent": user_agent,
"Referer": "https://accounts.coursera.org/signin",
"X-Requested-With": "XMLHttpRequest",
"X-CSRF2-Cookie": XCSRF2Cookie,
"X-CSRF2-Token": XCSRF2Token,
"X-CSRFToken": XCSRFToken,
"Cookie": cookie
}
coursera_session = requests.Session()
login_res = coursera_session.post(signin_url,
data=logininfo,
headers=post_headers,
)
if login_res.status_code == 200:
print "Login Successfully!"
else:
print login_res.text
import re
import urllib
page = urllib.urlopen("https://class.coursera.org/comnetworks-002/lecture")
html = page.read()
print html,