欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python爬取Coursera課程資源的詳細(xì)過程

 更新時(shí)間:2014年11月04日 15:50:13   投稿:hebedich  
這篇文章主要介紹了Python爬取Coursera課程資源的詳細(xì)過程,需要的朋友可以參考下

有時(shí)候我們需要把一些經(jīng)典的東西收藏起來,時(shí)時(shí)回味,而Coursera上的一些課程無疑就是經(jīng)典之作。Coursera中的大部分完結(jié)課程都提供了完整的配套教學(xué)資源,包括ppt,視頻以及字幕等,離線下來后會非常便于學(xué)習(xí)。很明顯,我們不會去一個(gè)文件一個(gè)文件的下載,只有傻子才那么干,程序員都是聰明人!

那我們聰明人準(zhǔn)備怎么辦呢?當(dāng)然是寫一個(gè)腳本來批量下載了。首先我們需要分析一下手工下載的流程:登錄自己的Coursera賬戶(有的課程需要我們登錄并選課后才能看到相應(yīng)的資源),在課程資源頁面里,找到相應(yīng)的文件鏈接,然后用喜歡的工具下載。

很簡單是吧?我們可以用程序來模仿以上的步驟,這樣就可以解放雙手了。整個(gè)程序分為三個(gè)部分就可以了:

登錄Coursera;在課程資源頁面里面找到資源鏈接;根據(jù)資源鏈接選擇合適的工具下載資源。

下面就來具體的實(shí)現(xiàn)以下吧!

登錄

剛開始時(shí)自己并沒有添加登錄模塊,以為訪客就可以下載相應(yīng)的課程資源,后來在測試comnetworks-002這門課程時(shí)發(fā)現(xiàn)訪客訪問資源頁面時(shí)會自動(dòng)跳轉(zhuǎn)到登錄界面,下圖是chrome在隱身模式訪問該課程資源頁面時(shí)的情況。

要想模擬登錄,我們先找到登錄的頁面,然后利用google的Developer Tools分析賬號密碼是如何上傳到服務(wù)器的。

我們在登錄頁面的表單中填入賬號密碼,然后點(diǎn)擊登錄。與此同時(shí),我們需要雙眼緊盯Developer Tools——Network,找到提交賬號信息的url。一般情況下,如果要向服務(wù)器提交信息,一般都用post方法,這里我們只需要先找到Method為post的url。悲劇的是,每次登錄賬號時(shí),Network里面都找不到提交賬戶信息的地址。猜測登錄成功后,直接跳轉(zhuǎn)到登錄成功后的頁面,想要找的內(nèi)容一閃而過了。

于是就隨便輸入了一組賬號密碼,故意登錄失敗,果真找到了post的頁面地址,如下圖:

地址為:https://accounts.coursera.org/api/v1/login。為了知道向服務(wù)器提交了哪些內(nèi)容,進(jìn)一步觀察post頁面中表單中內(nèi)容,如下圖:

我們看到一共有三個(gè)字段:

email:賬號的注冊郵箱password:賬號密碼webrequest:附加的字段,值為true。

接下來就動(dòng)手寫吧,我選擇用python的Requests庫來模擬登錄,關(guān)于Requests官網(wǎng)是這樣介紹的。

Requests is an elegant and simple HTTP library for Python, built for human beings.

事實(shí)上requests用起來確實(shí)簡單方便,不虧是專門為人類設(shè)計(jì)的http庫。requests提供了Session對象,可以用來在不同的請求中傳遞一些相同的數(shù)據(jù),比如在每次請求中都攜帶cookie。

初步的代碼如下:

signin_url = "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": "
                }
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

將表單中提交的內(nèi)容存放在字典中,然后作為data參數(shù)傳遞給Session.post函數(shù)。一般情況下,最好是加上請求User-Agent,Referer等請求頭部,User-Agent用來模擬瀏覽器請求,Referer用來告訴服務(wù)器我是從referer頁面跳轉(zhuǎn)到請求頁面的,有時(shí)候服務(wù)器會檢查請求的Referer字段來保證是從固定地址跳到當(dāng)前請求頁的。

上面片段的運(yùn)行結(jié)果很奇怪,顯示如下信息:Invalid CSRF Token。后來在github上面搜索到一個(gè)Coursera的批量下載腳本,發(fā)現(xiàn)人家發(fā)送頁面請求時(shí)headers多了XCSRF2Cookie, XCSRF2Token, XCSRFToken, cookie4個(gè)字段。于是又重新看了一下post頁面的請求頭部,發(fā)現(xiàn)確實(shí)有這幾個(gè)字段,估計(jì)是服務(wù)器端用來做一些限制的。

用瀏覽器登錄了幾次,發(fā)現(xiàn)XCSRF2Token, XCSRFToken是長度為24的隨機(jī)字符串,XCSRF2Cookie為"csrf2_token_"加上長度為8的隨機(jī)字符串。不過一直沒搞明白Cookie是怎么求出來的,不過看github上面代碼,Cookie似乎只是"csrftoken"和其他三個(gè)的組合,試了一下竟然可以。

在原來的代碼上添加以下部分就足夠了。

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": "
                "X-Requested-With": "XMLHttpRequest",
                "X-CSRF2-Cookie": XCSRF2Cookie,
                "X-CSRF2-Token": XCSRF2Token,
                "X-CSRFToken": XCSRFToken,
                "Cookie": cookie
                }

至此登錄功能初步實(shí)現(xiàn)。

分析資源鏈接

登錄成功后,我們只需要get到資源頁面的內(nèi)容,然后過濾出自己需要的資源鏈接就行了。資源頁面的地址很簡單,為https://class.coursera.org/name/lecture,其中name為課程名稱。比如對于課程comnetworks-002,資源頁面地址為https://class.coursera.org/comnetworks-002/lecture。

抓取到頁面資源后,我們需要分析html文件,這里選擇使用BeautifulSoup。BeautifulSoup是一個(gè)可以從HTML或XML文件中提取數(shù)據(jù)的Python庫,相當(dāng)強(qiáng)大。具體使用官網(wǎng)上有很詳細(xì)的文檔,這里不再贅述。在使用BeautifulSoup前,我們還得找出資源鏈接的規(guī)律,方便我們過濾。

其中課程每周的總題目為class=course-item-list-header的div標(biāo)簽下,每周的課程均在class=course-item-list-section-list的ul標(biāo)簽下,每節(jié)課程在一個(gè)li標(biāo)簽中,課程資源則在li標(biāo)簽中的div標(biāo)簽中。

查看了幾門課程之后,發(fā)現(xiàn)過濾資源鏈接的方法很簡單,如下:

ppt和ppt資源:用正則表達(dá)式匹配鏈接;字幕資源:找到title="Subtitles (srt)"的標(biāo)簽,取其href屬性;視頻資源:找到title="Video (MP4)"的標(biāo)簽,取其href屬性即可。

字幕和視頻也可以用正則表達(dá)式過濾,不過用BeautifulSoup根據(jù)title屬性來匹配,有更好的易讀性。而ppt和pdf資源,沒有固定的title屬性,只好利用正則表達(dá)式來匹配。

具體代碼如下:

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"]

下載資源

既然已經(jīng)得到了資源鏈接,下載部分就很容易了,這里我選擇使用curl來下載。具體思路很簡單,就是輸出curl resource_link -o file_name到一個(gè)種子文件中去,比如到feed.sh中。這樣只需要給種子文件執(zhí)行權(quán)限,然后運(yùn)行種子文件即可。

為了便于歸類課程資源,可以為課程每周的標(biāo)題建立一個(gè)文件夾,之后該周的所有課程均下載在該目錄下。為了方便我們快速定位到每節(jié)課的所有資源,可以把一節(jié)課的所有資源文件均命名為課名.文件類型。具體的實(shí)現(xiàn)比較簡單,這里不再給出具體程序了。可以看一下一個(gè)測試?yán)又械膄eed.sh文件,部分內(nèi)容如下:

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'

到這里為止,我們已經(jīng)成功完成爬取Coursera課程資源的目標(biāo),具體的代碼放在gist上。使用時(shí),我們只需要運(yùn)行程序,并把課程名稱作為參數(shù)傳遞給程序就可以了(這里的課程名稱并不是整個(gè)課程的完整名字,而是在課程介紹頁面地址中的縮略名字,比如Computer Networks這門課,課程名稱是comnetworks-002)。

其實(shí),這個(gè)程序可以看做一個(gè)簡單的小爬蟲程序了,下面粗略介紹下爬蟲的概念。

一點(diǎn)都不簡單的爬蟲

關(guān)于什么是爬蟲,wiki上是這樣說的

A Web crawler is an Internet bot that systematically browses the World Wide Web, typically for the purpose of Web indexing.

爬蟲的總體架構(gòu)圖如下(圖片來自wiki):

簡單來說,爬蟲從Scheduler中獲取初始的urls,下載相應(yīng)的頁面,存儲有用的數(shù)據(jù),同時(shí)分析該頁面中的鏈接,如果已經(jīng)訪問就pass,沒訪問的話加入到Scheduler中等待抓取頁面。

當(dāng)然有一些協(xié)議來約束爬蟲的行為規(guī)范,比如許多網(wǎng)站都有一個(gè)robots.txt文件來規(guī)定網(wǎng)站哪些內(nèi)容可以被爬取,哪些不可以。

每個(gè)搜索引擎背后都有一個(gè)強(qiáng)大的爬蟲程序,把觸角伸到網(wǎng)絡(luò)中的所有角落,不斷去收集有用信息,并建立索引。這種搜索引擎級別的爬蟲實(shí)現(xiàn)起來非常復(fù)雜,因?yàn)榫W(wǎng)絡(luò)上的頁面數(shù)量太過龐大,只是遍歷他們就已經(jīng)很困難了,更不要說去分析頁面信息,并建立索引了。

實(shí)際應(yīng)用中,我們只需要爬取特定站點(diǎn),抓取少量的資源,這樣實(shí)現(xiàn)起來簡單很多。不過仍然有許多讓人頭疼的問題,比如許多頁面元素是javascript生成的,這時(shí)候我們需要一個(gè)javascript引擎,渲染出整個(gè)頁面,再加以過濾。

更糟糕的是,許多站點(diǎn)都會用一些措施來阻止爬蟲爬取資源,比如限定同一IP一段時(shí)間的訪問次數(shù),或者是限制兩次操作的時(shí)間間隔,加入驗(yàn)證碼等等。絕大多數(shù)情況下,我們不知道服務(wù)器端是如何防止爬蟲的,所以要想讓爬蟲工作起來確實(shí)挺難的。

相關(guān)文章

  • django使用xlwt導(dǎo)出excel文件實(shí)例代碼

    django使用xlwt導(dǎo)出excel文件實(shí)例代碼

    這篇文章主要介紹了django使用xlwt導(dǎo)出excel文件實(shí)例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • python?中?os.walk()?函數(shù)詳解

    python?中?os.walk()?函數(shù)詳解

    os.walk()是一種遍歷目錄數(shù)的函數(shù),它以一種深度優(yōu)先的策略(depth-first)訪問指定的目錄。這篇文章主要介紹了python?中?os.walk()?函數(shù),需要的朋友可以參考下
    2021-11-11
  • python-docx 頁面設(shè)置詳解

    python-docx 頁面設(shè)置詳解

    今天小編就為大家分享一篇python docx 中頁面的設(shè)置,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-10-10
  • Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)列表與元組示例詳解

    Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)列表與元組示例詳解

    這篇文章主要給大家介紹了關(guān)于Python內(nèi)置數(shù)據(jù)結(jié)構(gòu)列表與元組的相關(guān)資料,列表是順序存儲的數(shù)據(jù)結(jié)構(gòu),類似于數(shù)據(jù)結(jié)構(gòu)中的順序表,在存儲上是相連的一大塊內(nèi)存空間,在物理和邏輯上都是連續(xù)的,需要的朋友可以參考下
    2021-08-08
  • 在Pycharm中設(shè)置默認(rèn)自動(dòng)換行的方法

    在Pycharm中設(shè)置默認(rèn)自動(dòng)換行的方法

    今天小編就為大家分享一篇在Pycharm中設(shè)置默認(rèn)自動(dòng)換行的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • Python中的日期時(shí)間處理詳解

    Python中的日期時(shí)間處理詳解

    Python程序能用很多方式處理日期和時(shí)間。轉(zhuǎn)換日期格式是一個(gè)常見的例行瑣事,這篇文章主要介紹了Python中的日期時(shí)間處理的幾種方式的區(qū)別和聯(lián)系,需要的朋友可以參考下
    2016-11-11
  • python函數(shù)的重新定義及練習(xí)

    python函數(shù)的重新定義及練習(xí)

    這篇文章主要為大家詳細(xì)介紹了python的函數(shù),使用python,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • python SSH模塊登錄,遠(yuǎn)程機(jī)執(zhí)行shell命令實(shí)例解析

    python SSH模塊登錄,遠(yuǎn)程機(jī)執(zhí)行shell命令實(shí)例解析

    這篇文章主要介紹了python SSH模塊登錄,遠(yuǎn)程機(jī)執(zhí)行shell命令實(shí)例解析,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • pycharm日志總是彈出“無法運(yùn)行Git,未安裝Git”的問題

    pycharm日志總是彈出“無法運(yùn)行Git,未安裝Git”的問題

    這篇文章主要介紹了pycharm日志總是彈出“無法運(yùn)行Git,未安裝Git”的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Python pickle模塊用法實(shí)例

    Python pickle模塊用法實(shí)例

    這篇文章主要介紹了Python pickle模塊用法實(shí)例,python的pickle模塊實(shí)現(xiàn)了基本的數(shù)據(jù)序列和反序列化,需要的朋友可以參考下
    2015-04-04

最新評論