日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

手把手教你用python抓網(wǎng)頁數(shù)據(jù)

 海漩渦 2014-05-07
本帖最后由 EroicaCMCS 于 2014-2-16 20:29 編輯

前言:
數(shù)據(jù)科學(xué)越來越火了,網(wǎng)頁是數(shù)據(jù)很大的一個(gè)來源。最近很多人問怎么抓網(wǎng)頁數(shù)據(jù),據(jù)我所知,常見的編程語言(C++,java,python)都可以實(shí)現(xiàn)抓網(wǎng)頁數(shù)據(jù),甚至很多統(tǒng)計(jì)\計(jì)算的語言(R,Matlab)都有可以實(shí)現(xiàn)和網(wǎng)站交互的包。本人試過用java,python,R抓網(wǎng)頁,感覺語法各有差異,邏輯上是一樣的。我準(zhǔn)備用python來大概講講抓網(wǎng)頁是什么概念,具體的內(nèi)容要自己看手冊或者google別人的博客,這里算是拋磚引玉了。水平有限,出現(xiàn)錯(cuò)誤或者有更好的辦法,歡迎討論。

步驟一:熟悉Python的基本語法。
已經(jīng)熟悉Python的直接跳到步驟二。
Python是門比較容易入門的編程語言,如何上手視編程基礎(chǔ)而定。
(1) 如果有一定編程的基礎(chǔ),建議看google's python class,鏈接https://developers.google.com/edu/python/?hl=zh-CN&csw=1
這個(gè)是一個(gè)為期兩天的短期培訓(xùn)課程(當(dāng)然,是兩個(gè)全天),大概是七個(gè)視頻,每個(gè)視頻之后給編程作業(yè),每個(gè)作業(yè)一個(gè)小時(shí)之內(nèi)可以完成。這是我學(xué)習(xí)python的第二門課(第一門是codecademy的python,很早之前看的,很多內(nèi)容都記不得了),當(dāng)時(shí)每天看視頻+編程作業(yè)一個(gè)多小時(shí),六天弄完,效果還不錯(cuò),用python寫基本的程序沒有問題。
(2) 如果是沒有任何編程基礎(chǔ),建議看coursera上Rice University開的An Introduction to Interactive Programming in Python。這門課我沒有跟過,但是看coursetalk的評論反映非常好,地里也有同學(xué)評論(點(diǎn)這里),課程鏈接:https://www./course/interactivepython。Udacity上的CS101也是不錯(cuò)的選擇,地里有相關(guān)的討論帖(點(diǎn)這里),而且這門課就叫做build a search engine,會專門講一些和網(wǎng)絡(luò)相關(guān)的module。其他學(xué)習(xí)資源還有code school和codecademy,這些資源也是挺不錯(cuò)的,但是編程量太少,初學(xué)者還是系統(tǒng)的跟課、多練練手來打好基礎(chǔ)吧。
當(dāng)然,每個(gè)人的偏好不同,我推薦的不一定適合你??梢韵瓤纯催@個(gè)帖子【長期加分貼】介紹你上過的公開課里面其他人是怎么說的,或者上看看課程評論,再決定吧。


步驟二:學(xué)會如何與網(wǎng)站建立鏈接,得到網(wǎng)頁數(shù)據(jù)。
寫腳本與網(wǎng)站進(jìn)行交互,要熟悉python和網(wǎng)頁相關(guān)的幾個(gè)module(urllib,urllib2,httplib)中的一個(gè),知道一個(gè)即可,其他的都類似的。這三個(gè)是python提供的和網(wǎng)頁交互的基本module,還有其他的一些,比如:mechanize和scrappy,我沒有用過,可能有更好的性能,歡迎了解的來補(bǔ)充?;镜木W(wǎng)頁抓取,前面的三個(gè)module足矣。
下面的代碼演示如何用urllib2與google scholar進(jìn)行交互,獲得網(wǎng)頁信息。
  1. # 導(dǎo)入模塊 urllib2
  2. import urllib2

  3. # 隨便查詢一篇文章,比如On random graph。對每一個(gè)查詢google 
  4. # scholar都有一個(gè)url,這個(gè)url形成的規(guī)則是要自己分析的。
  5. query = 'On+random+graph'
  6. url = 'http://scholar.google.com/scholar?hl=en&q=' + query + '&btnG=&as_sdt=1%2C5&as_sdtp='
  7. # 設(shè)置頭文件。抓取有些的網(wǎng)頁不需要專門設(shè)置頭文件,但是這里如果不設(shè)置的話,
  8. # google會認(rèn)為是機(jī)器人不允許訪問。另外訪問有些網(wǎng)站還有設(shè)置Cookie,這個(gè)會相對復(fù)雜一些,
  9. # 這里暫時(shí)不提。關(guān)于怎么知道頭文件該怎么寫,一些插件可以看到你用的瀏覽器和網(wǎng)站交互的
  10. # 頭文件(這種工具很多瀏覽器是自帶的),我用的是firefox的firebug插件。
  11. header = {'Host': 'scholar.google.com',
  12. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0',
  13. 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  14. 'Accept-Encoding': 'gzip, deflate',
  15. 'Connection': 'keep-alive'}
  16. # 建立連接請求,這時(shí)google的服務(wù)器返回頁面信息給con這個(gè)變量,con是一個(gè)對象
  17. req = urllib2.Request(url, headers = header) 
  18. con = urllib2.urlopen( req )
  19. # 對con這個(gè)對象調(diào)用read()方法,返回的是html頁面,也就是有html標(biāo)簽的純文本
  20. doc = con.read()
  21. # 關(guān)閉連接。就像讀完文件要關(guān)閉文件一樣,如果不關(guān)閉有時(shí)可以、但有時(shí)會有問題,
  22. # 所以作為一個(gè)守法的好公民,還是關(guān)閉連接好了。
  23. con.close()
復(fù)制代碼
以上的代碼就把在google scholar上查詢On Random Graph的結(jié)果返回到doc這個(gè)變量中了,這個(gè)和你打開google scholar搜索On Random Graph,然后將網(wǎng)頁右鍵保存的效果是一樣的。

步驟三、解析網(wǎng)頁
上面的步驟得到了網(wǎng)頁的信息,但是包括了html標(biāo)簽,你要把這些標(biāo)簽去掉,然后從html文本中整理出有用的信息,
你需要解析這個(gè)網(wǎng)頁。
解析網(wǎng)頁的方法:
(1) 正則表達(dá)式。正則表達(dá)式很有用,熟悉它節(jié)省很多的時(shí)間,有時(shí)候清洗數(shù)據(jù)不用寫腳本或者在數(shù)據(jù)庫上查詢,直接在notepad++上用正則表達(dá)式組合使用就行了。如何學(xué)習(xí)正則表達(dá)式建議看:正則表達(dá)式30分鐘入門教程,鏈接:http:///tutorials/regex/regex.htm
(2) BeautifulSoup模塊。BeautifulSoup是一個(gè)很強(qiáng)大的模塊,能把html文件解析成一個(gè)對象,這個(gè)對象是一棵樹。我們都知道html文件是樹狀的,比如 body -> table -> tbody -> tr,對于tbody這個(gè)節(jié)點(diǎn),有很多個(gè)tr的子節(jié)點(diǎn)。BeautifulSoup可以很方便的取到特定的節(jié)點(diǎn),對單個(gè)節(jié)點(diǎn)也可以取它的sibling node。網(wǎng)上有很多相關(guān)的說明,這里不細(xì)說,只演示簡單的代碼:
(3) 上面兩種方法結(jié)合使用。
  1. # 導(dǎo)入BeautifulSoup模塊和re模塊,re是python中正則表達(dá)式的模塊
  2. import BeautifulSoup
  3. import re
  4. # 生成一個(gè)soup對象,doc就是步驟二中提到的
  5. soup = BeautifulSoup.BeautifulSoup(doc)
  6. # 抓取論文標(biāo)題,作者,簡短描述,引用次數(shù),版本數(shù),引用它的文章列表的超鏈接
  7. # 這里還用了一些正則表達(dá)式,不熟悉的先無知它好了。至于'class' : 'gs_rt'中
  8. # 'gs_rt'是怎么來的,這個(gè)是分析html文件肉眼看出來的。上面提到的firebug插件
  9. # 讓這個(gè)變的很簡單,只要一點(diǎn)網(wǎng)頁,就可以知道對應(yīng)的html 標(biāo)簽的位置和屬性,
  10. # 相當(dāng)好用。
  11. paper_name = soup.html.body.find('h3', {'class' : 'gs_rt'}).text
  12. paper_name = re.sub(r'\[.*\]', '', paper_name) # eliminate '[]' tags like '[PDF]'
  13. paper_author = soup.html.body.find('div', {'class' : 'gs_a'}).text
  14. paper_desc = soup.html.body.find('div', {'class' : 'gs_rs'}).text
  15. temp_str = soup.html.body.find('div', {'class' : 'gs_fl'}).text
  16. temp_re = re.match(r'[A-Za-z\s]+(\d*)[A-Za-z\s]+(\d*)', temp_str)
  17. citeTimes = temp_re.group(1)
  18. versionNum = temp_re.group(2)
  19. if citeTimes == '':
  20.   citeTimes = '0'
  21. if versionNum == '':
  22.   versionNum = '0'
  23. citedPaper_href = soup.html.body.find('div', {'class' : 'gs_fl'}).a.attrs[0][1]
復(fù)制代碼

這些都是我在一個(gè)分析citation network的項(xiàng)目的代碼。順便一提,我從google scholar上抓取paper的信息以及引用列表的信息,訪問了大概1900次左右的時(shí)候給google block了,導(dǎo)致這個(gè)片區(qū)的ip一時(shí)無法登陸google scholar。

步驟四:存取數(shù)據(jù)
好不容易抓了數(shù)據(jù),現(xiàn)在只是存儲在內(nèi)存中,必須保存起來才能利用。
(1) 最簡單的方法之把數(shù)據(jù)寫進(jìn)txt文件中,Python中可以用如下代碼實(shí)現(xiàn):

  1. # 打開文件webdata.txt,生成對象file,這個(gè)文件可以是不存在的,參數(shù)a表示往里面添加。
  2. # 還有別的參數(shù),比如'r'只能讀但不能寫入,'w'可以寫入但是會刪除原來的記錄等等
  3. file = open('webdata.txt','a')
  4. line = paper_name + '#' + paper_author + '#' + paper_desc + '#' + citeTimes + '\n'
  5. # 對象file的write方法將字符串line寫入file中
  6. file = file.write(line)
  7. # 再一次的,做個(gè)隨手關(guān)閉文件的好青年
  8. file.close()
復(fù)制代碼
這樣,就把從網(wǎng)頁上抓到并且解析了的數(shù)據(jù)存儲到本地了,是不是很簡單?
(2) 當(dāng)然,你也可以不寫入txt文件中,而是直接連接數(shù)據(jù)庫,python中的MySQLdb模塊可以實(shí)現(xiàn)和MySQL數(shù)據(jù)庫的交互,把數(shù)據(jù)直接倒到數(shù)據(jù)庫里面,與MySQL數(shù)據(jù)庫建立鏈接的邏輯和與網(wǎng)站服務(wù)器建立鏈接的邏輯差不多。如果之前有學(xué)習(xí)過數(shù)據(jù)庫,學(xué)習(xí)用MySQLdb模塊實(shí)現(xiàn)和數(shù)據(jù)庫的交互是很簡單的;如果沒有,則要借助在coursera\Stanford openEdX平臺上都有開設(shè)的Introduction to Database來系統(tǒng)學(xué)習(xí),w3school用來參考或者當(dāng)成手冊。
Python能夠鏈接數(shù)據(jù)庫的前提是數(shù)據(jù)庫是開著的,我用的是 win7 + MySQL5.5,數(shù)據(jù)庫在本地。
  1. %可以用cmd開啟數(shù)據(jù)庫,啟動命令是:
  2. net start mysql55
  3. %關(guān)閉命令是:
  4. net stop mysql55
復(fù)制代碼
使用MySQLdb模塊代碼示例:
  1. # 導(dǎo)入 MySQLdb模塊
  2. import MySQLdb
  3. # 和服務(wù)器建立鏈接,host是服務(wù)器ip,我的MySQL數(shù)據(jù)庫搭建在本機(jī),默認(rèn)的是127.0.0.1,
  4. # 用戶、密碼、數(shù)據(jù)庫名稱對應(yīng)著照輸就行了,默認(rèn)的端口號是3306,charset是編碼方式,
  5. # 默認(rèn)的是utf8(也有可能是gbk,看安裝的版本)。
  6. conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='yourPassword', db='dbname', port=3306, charset='utf8')
  7. # 建立cursor
  8. cur = conn.cursor()
  9. # 通過對象cur的execute()方法執(zhí)行SQL語句
  10. cur.execute("select * from citeRelation where paperName = 'On Random Graph'")
  11. # fetchall()方法獲得查詢結(jié)果,返回的是一個(gè)list,可以直接這樣查詢:list[i][j],
  12. # i表示查詢結(jié)果中的第i+1條record,j表示這條記錄的第j+1個(gè)attribute(別忘了python從0開始計(jì)數(shù))
  13. list = cur.fetchall()
  14. # 也可以進(jìn)行delete,drop,insert,update等操作,比如:
  15. sql = "update studentCourseRecord set fail = 1 where studentID = '%s' and semesterID = '%s' and courseID = '%s'" %(studentID,course[0],course[1])
  16. cur.execute(sql)
  17. # 與查詢不同的是,執(zhí)行完delete,insert,update這些語句后必須執(zhí)行下面的命令才能成功更新數(shù)據(jù)庫
  18. conn.commit()
  19. # 一如既往的,用完了之后記得關(guān)閉cursor,然后關(guān)閉鏈接
  20. cur.close()
  21. conn.close()
復(fù)制代碼

這樣就實(shí)現(xiàn)了Python和數(shù)據(jù)庫之間的交互。除了MySQL數(shù)據(jù)庫外,python的PyGreSQL模塊可以支持postgreSQL數(shù)據(jù)庫,道理類似的。還有,如果你的網(wǎng)頁里面包含了中文,設(shè)置編碼格式會非常的麻煩,需要服務(wù)器、Python、數(shù)據(jù)庫和數(shù)據(jù)庫界面采用相同的編碼格式才能不出現(xiàn)亂碼,如果真的出現(xiàn)了中文亂碼的問題,請相信,你不是一個(gè)人??!去google一下吧,成千上萬的人碰到過這種問題。
關(guān)于編碼的問題,附一篇我看到的博文<python編碼問題總結(jié)>:
http://www./1258.html

后記:
上面介紹了抓取網(wǎng)頁數(shù)據(jù)的方法,抓取數(shù)據(jù)只是一小步,如何分析數(shù)據(jù)就是大學(xué)問了,歡迎討論。
上面有什么地方講不清楚的,歡迎交流。

特別注意:
大規(guī)模抓取網(wǎng)站會給網(wǎng)站的服務(wù)器帶來很大的壓力,盡量選擇服務(wù)器相對輕松的時(shí)段(比如凌晨)。網(wǎng)站很多,不要拿一畝三分地來做試驗(yàn)。
Python的time模塊的sleep()方法可以讓程序暫停一段時(shí)間,比如time.sleep(1)讓程序運(yùn)行到這里的時(shí)候暫停1秒。適時(shí)地暫停可以緩解服務(wù)器的壓力,也可以保護(hù)自己的硬盤,正好碼久了睡個(gè)覺,或者去趟gym,結(jié)果就出來了。


更新:
2014年2月15日,更改了幾處打字錯(cuò)誤;添加了相關(guān)課程鏈接;增加了udacity CS101的介紹;增加了MySQLdb模塊的介紹。
2014年2月16日,增加了介紹編碼方式的博文鏈接。







分享到:3
已有 15 人評分大米收起理由
 Hey_Qian+ 3贊~
 sy10017667+ 100高手
 真威武+ 150好東西,學(xué)習(xí)了
 紫夜依晨+ 3感謝分享!
 dongr87+ 3很細(xì)致,受教了!
 hanzhangqin8+ 3感謝分享~
 hercule24+ 3牛逼!
 melodylin32+ 2膩害!辛苦吶!
 KikSamuel+ 3我就只能加3分....
 sanguine+ 150太贊了!?。?/td>
 anonym+ 150都是版主 水平差的太多了%>_<%
 rsun+ 150牛逼!細(xì)致!
 alonever+ 150
 Kimurate+ 50再接再厲!
 小K+ 200

總評分: 大米 + 1120   查看全部評分

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多