手把手教你用python抓網頁數據
07-02
本帖最後由 EroicaCMCS 於 2014-2-16 20:29 編輯前言:數據科學越來越火了,網頁是數據很大的一個來源。最近很多人問怎麼抓網頁數據,據我所知,常見的編程語言(C++,java,python)都可以實現抓網頁數據,甚至很多統計計算的語言(R,Matlab)都有可以實現和網站交互的包。本人試過用java,python,R抓網頁,感覺語法各有差異,邏輯上是一樣的。我準備用python來大概講講抓網頁是什麼概念,具體的內容要自己看手冊或者google別人的博客,這裡算是拋磚引玉了。水平有限,出現錯誤或者有更好的辦法,歡迎討論。步驟一:熟悉Python的基本語法。已經熟悉Python的直接跳到步驟二。Python是門比較容易入門的編程語言,如何上手視編程基礎而定。(1) 如果有一定編程的基礎,建議看google"s python class,鏈接https://developers.google.com/edu/python/?hl=zh-CN&csw=1這個是一個為期兩天的短期培訓課程(當然,是兩個全天),大概是七個視頻,每個視頻之後給編程作業,每個作業一個小時之內可以完成。這是我學習python的第二門課(第一門是codecademy的python,很早之前看的,很多內容都記不得了),當時每天看視頻+編程作業一個多小時,六天弄完,效果還不錯,用python寫基本的程序沒有問題。(2) 如果是沒有任何編程基礎,建議看coursera上Rice University開的An Introduction to Interactive Programming in Python。這門課我沒有跟過,但是看coursetalk的評論反映非常好,地里也有同學評論(點這裡),課程鏈接:https://www.coursera.org/course/interactivepython。Udacity上的CS101也是不錯的選擇,地里有相關的討論帖(點這裡),而且這門課就叫做build a search engine,會專門講一些和網路相關的module。其他學習資源還有code school和codecademy,這些資源也是挺不錯的,但是編程量太少,初學者還是系統的跟課、多練練手來打好基礎吧。當然,每個人的偏好不同,我推薦的不一定適合你。可以先看看這個帖子【長期加分貼】介紹你上過的公開課裡面其他人是怎麼說的,或者上coursetalk.org看看課程評論,再決定吧。步驟二:學會如何與網站建立鏈接,得到網頁數據。寫腳本與網站進行交互,要熟悉python和網頁相關的幾個module(urllib,urllib2,httplib)中的一個,知道一個即可,其他的都類似的。這三個是python提供的和網頁交互的基本module,還有其他的一些,比如:mechanize和scrappy,我沒有用過,可能有更好的性能,歡迎了解的來補充。基本的網頁抓取,前面的三個module足矣。下面的代碼演示如何用urllib2與google scholar進行交互,獲得網頁信息。# 導入模塊 urllib2import urllib2# 隨便查詢一篇文章,比如On random graph。對每一個查詢google# scholar都有一個url,這個url形成的規則是要自己分析的。query = "On+random+graph"url = "http://scholar.google.com/scholar?hl=en&q=" + query + "&btnG=&as_sdt=1%2C5&as_sdtp="# 設置頭文件。抓取有些的網頁不需要專門設置頭文件,但是這裡如果不設置的話,# google會認為是機器人不允許訪問。另外訪問有些網站還有設置Cookie,這個會相對複雜一些,# 這裡暫時不提。關於怎麼知道頭文件該怎麼寫,一些插件可以看到你用的瀏覽器和網站交互的# 頭文件(這種工具很多瀏覽器是自帶的),我用的是firefox的firebug插件。header = {"Host": "scholar.google.com","User-Agent": "Mozilla/5.0 (Windows NT 6.1; rv:26.0) Gecko/20100101 Firefox/26.0","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Accept-Encoding": "gzip, deflate","Connection": "keep-alive"}# 建立連接請求,這時google的伺服器返回頁面信息給con這個變數,con是一個對象req = urllib2.Request(url, headers = header)con = urllib2.urlopen( req )# 對con這個對象調用read()方法,返回的是html頁面,也就是有html標籤的純文本doc = con.read()# 關閉連接。就像讀完文件要關閉文件一樣,如果不關閉有時可以、但有時會有問題,# 所以作為一個守法的好公民,還是關閉連接好了。con.close()複製代碼以上的代碼就把在google scholar上查詢On Random Graph的結果返回到doc這個變數中了,這個和你打開google scholar搜索On Random Graph,然後將網頁右鍵保存的效果是一樣的。步驟三、解析網頁上面的步驟得到了網頁的信息,但是包括了html標籤,你要把這些標籤去掉,然後從html文本中整理出有用的信息,你需要解析這個網頁。解析網頁的方法:(1) 正則表達式。正則表達式很有用,熟悉它節省很多的時間,有時候清洗數據不用寫腳本或者在資料庫上查詢,直接在notepad++上用正則表達式組合使用就行了。如何學習正則表達式建議看:正則表達式30分鐘入門教程,鏈接:http://deerchao.net/tutorials/regex/regex.htm(2) BeautifulSoup模塊。BeautifulSoup是一個很強大的模塊,能把html文件解析成一個對象,這個對象是一棵樹。我們都知道html文件是樹狀的,比如 body -> table -> tbody -> tr,對於tbody這個節點,有很多個tr的子節點。BeautifulSoup可以很方便的取到特定的節點,對單個節點也可以取它的sibling node。網上有很多相關的說明,這裡不細說,只演示簡單的代碼:(3) 上面兩種方法結合使用。# 導入BeautifulSoup模塊和re模塊,re是python中正則表達式的模塊import BeautifulSoupimport re# 生成一個soup對象,doc就是步驟二中提到的soup = BeautifulSoup.BeautifulSoup(doc)# 抓取論文標題,作者,簡短描述,引用次數,版本數,引用它的文章列表的超鏈接# 這裡還用了一些正則表達式,不熟悉的先無知它好了。至於"class" : "gs_rt"中# "gs_rt"是怎麼來的,這個是分析html文件肉眼看出來的。上面提到的firebug插件# 讓這個變的很簡單,只要一點網頁,就可以知道對應的html 標籤的位置和屬性,# 相當好用。paper_name = soup.html.body.find("h3", {"class" : "gs_rt"}).textpaper_name = re.sub(r"[.*]", "", paper_name) # eliminate "[]" tags like "[PDF]"paper_author = soup.html.body.find("div", {"class" : "gs_a"}).textpaper_desc = soup.html.body.find("div", {"class" : "gs_rs"}).texttemp_str = soup.html.body.find("div", {"class" : "gs_fl"}).texttemp_re = re.match(r"[A-Za-zs]+(d*)[A-Za-zs]+(d*)", temp_str)citeTimes = temp_re.group(1)versionNum = temp_re.group(2)if citeTimes == "":citeTimes = "0"if versionNum == "":versionNum = "0"citedPaper_href = soup.html.body.find("div", {"class" : "gs_fl"}).a.attrs[0][1]複製代碼這些都是我在一個分析citation network的項目的代碼。順便一提,我從google scholar上抓取paper的信息以及引用列表的信息,訪問了大概1900次左右的時候給google block了,導致這個片區的ip一時無法登陸google scholar。步驟四:存取數據好不容易抓了數據,現在只是存儲在內存中,必須保存起來才能利用。(1) 最簡單的方法之把數據寫進txt文件中,Python中可以用如下代碼實現:# 打開文件webdata.txt,生成對象file,這個文件可以是不存在的,參數a表示往裡面添加。# 還有別的參數,比如"r"只能讀但不能寫入,"w"可以寫入但是會刪除原來的記錄等等file = open("webdata.txt","a")line = paper_name + "#" + paper_author + "#" + paper_desc + "#" + citeTimes + "
"# 對象file的write方法將字元串line寫入file中file = file.write(line)# 再一次的,做個隨手關閉文件的好青年file.close()複製代碼這樣,就把從網頁上抓到並且解析了的數據存儲到本地了,是不是很簡單?(2) 當然,你也可以不寫入txt文件中,而是直接連接資料庫,python中的MySQLdb模塊可以實現和MySQL資料庫的交互,把數據直接倒到資料庫裡面,與MySQL資料庫建立鏈接的邏輯和與網站伺服器建立鏈接的邏輯差不多。如果之前有學習過資料庫,學慣用MySQLdb模塊實現和資料庫的交互是很簡單的;如果沒有,則要藉助在courseraStanford openEdX平台上都有開設的Introduction to Database來系統學習,w3school用來參考或者當成手冊。Python能夠鏈接資料庫的前提是資料庫是開著的,我用的是 win7 + MySQL5.5,資料庫在本地。%可以用cmd開啟資料庫,啟動命令是:net start mysql55%關閉命令是:net stop mysql55複製代碼使用MySQLdb模塊代碼示例:# 導入 MySQLdb模塊import MySQLdb# 和伺服器建立鏈接,host是伺服器ip,我的MySQL資料庫搭建在本機,默認的是127.0.0.1,# 用戶、密碼、資料庫名稱對應著照輸就行了,默認的埠號是3306,charset是編碼方式,# 默認的是utf8(也有可能是gbk,看安裝的版本)。conn = MySQLdb.connect(host="127.0.0.1", user="root", passwd="yourPassword", db="dbname", port=3306, charset="utf8")# 建立cursorcur = conn.cursor()# 通過對象cur的execute()方法執行SQL語句cur.execute("select * from citeRelation where paperName = "On Random Graph"")# fetchall()方法獲得查詢結果,返回的是一個list,可以直接這樣查詢:list[i][j],# i表示查詢結果中的第i+1條record,j表示這條記錄的第j+1個attribute(別忘了python從0開始計數)list = cur.fetchall()# 也可以進行delete,drop,insert,update等操作,比如:sql = "update studentCourseRecord set fail = 1 where studentID = "%s" and semesterID = "%s" and courseID = "%s"" %(studentID,course[0],course[1])cur.execute(sql)# 與查詢不同的是,執行完delete,insert,update這些語句後必須執行下面的命令才能成功更新資料庫conn.commit()# 一如既往的,用完了之後記得關閉cursor,然後關閉鏈接cur.close()conn.close()複製代碼這樣就實現了Python和資料庫之間的交互。除了MySQL資料庫外,python的PyGreSQL模塊可以支持postgreSQL資料庫,道理類似的。還有,如果你的網頁裡面包含了中文,設置編碼格式會非常的麻煩,需要伺服器、Python、資料庫和資料庫界面採用相同的編碼格式才能不出現亂碼,如果真的出現了中文亂碼的問題,請相信,你不是一個人!!去google一下吧,成千上萬的人碰到過這種問題。關於編碼的問題,附一篇我看到的博文<python編碼問題總結>:http://www.xprogrammer.com/1258.html後記:上面介紹了抓取網頁數據的方法,抓取數據只是一小步,如何分析數據就是大學問了,歡迎討論。上面有什麼地方講不清楚的,歡迎交流。特別注意:大規模抓取網站會給網站的伺服器帶來很大的壓力,盡量選擇伺服器相對輕鬆的時段(比如凌晨)。網站很多,不要拿一畝三分地來做試驗。Python的time模塊的sleep()方法可以讓程序暫停一段時間,比如time.sleep(1)讓程序運行到這裡的時候暫停1秒。適時地暫停可以緩解伺服器的壓力,也可以保護自己的硬碟,正好碼久了睡個覺,或者去趟gym,結果就出來了。更新:2014年2月15日,更改了幾處打字錯誤;添加了相關課程鏈接;增加了udacity CS101的介紹;增加了MySQLdb模塊的介紹。2014年2月16日,增加了介紹編碼方式的博文鏈接。分享到:已有15人評分大米理由
"# 對象file的write方法將字元串line寫入file中file = file.write(line)# 再一次的,做個隨手關閉文件的好青年file.close()複製代碼這樣,就把從網頁上抓到並且解析了的數據存儲到本地了,是不是很簡單?(2) 當然,你也可以不寫入txt文件中,而是直接連接資料庫,python中的MySQLdb模塊可以實現和MySQL資料庫的交互,把數據直接倒到資料庫裡面,與MySQL資料庫建立鏈接的邏輯和與網站伺服器建立鏈接的邏輯差不多。如果之前有學習過資料庫,學慣用MySQLdb模塊實現和資料庫的交互是很簡單的;如果沒有,則要藉助在courseraStanford openEdX平台上都有開設的Introduction to Database來系統學習,w3school用來參考或者當成手冊。Python能夠鏈接資料庫的前提是資料庫是開著的,我用的是 win7 + MySQL5.5,資料庫在本地。%可以用cmd開啟資料庫,啟動命令是:net start mysql55%關閉命令是:net stop mysql55複製代碼使用MySQLdb模塊代碼示例:# 導入 MySQLdb模塊import MySQLdb# 和伺服器建立鏈接,host是伺服器ip,我的MySQL資料庫搭建在本機,默認的是127.0.0.1,# 用戶、密碼、資料庫名稱對應著照輸就行了,默認的埠號是3306,charset是編碼方式,# 默認的是utf8(也有可能是gbk,看安裝的版本)。conn = MySQLdb.connect(host="127.0.0.1", user="root", passwd="yourPassword", db="dbname", port=3306, charset="utf8")# 建立cursorcur = conn.cursor()# 通過對象cur的execute()方法執行SQL語句cur.execute("select * from citeRelation where paperName = "On Random Graph"")# fetchall()方法獲得查詢結果,返回的是一個list,可以直接這樣查詢:list[i][j],# i表示查詢結果中的第i+1條record,j表示這條記錄的第j+1個attribute(別忘了python從0開始計數)list = cur.fetchall()# 也可以進行delete,drop,insert,update等操作,比如:sql = "update studentCourseRecord set fail = 1 where studentID = "%s" and semesterID = "%s" and courseID = "%s"" %(studentID,course[0],course[1])cur.execute(sql)# 與查詢不同的是,執行完delete,insert,update這些語句後必須執行下面的命令才能成功更新資料庫conn.commit()# 一如既往的,用完了之後記得關閉cursor,然後關閉鏈接cur.close()conn.close()複製代碼這樣就實現了Python和資料庫之間的交互。除了MySQL資料庫外,python的PyGreSQL模塊可以支持postgreSQL資料庫,道理類似的。還有,如果你的網頁裡面包含了中文,設置編碼格式會非常的麻煩,需要伺服器、Python、資料庫和資料庫界面採用相同的編碼格式才能不出現亂碼,如果真的出現了中文亂碼的問題,請相信,你不是一個人!!去google一下吧,成千上萬的人碰到過這種問題。關於編碼的問題,附一篇我看到的博文<python編碼問題總結>:http://www.xprogrammer.com/1258.html後記:上面介紹了抓取網頁數據的方法,抓取數據只是一小步,如何分析數據就是大學問了,歡迎討論。上面有什麼地方講不清楚的,歡迎交流。特別注意:大規模抓取網站會給網站的伺服器帶來很大的壓力,盡量選擇伺服器相對輕鬆的時段(比如凌晨)。網站很多,不要拿一畝三分地來做試驗。Python的time模塊的sleep()方法可以讓程序暫停一段時間,比如time.sleep(1)讓程序運行到這裡的時候暫停1秒。適時地暫停可以緩解伺服器的壓力,也可以保護自己的硬碟,正好碼久了睡個覺,或者去趟gym,結果就出來了。更新:2014年2月15日,更改了幾處打字錯誤;添加了相關課程鏈接;增加了udacity CS101的介紹;增加了MySQLdb模塊的介紹。2014年2月16日,增加了介紹編碼方式的博文鏈接。分享到:已有15人評分大米理由
Hey_Qian+ 3贊~
sy10017667+ 100高手
真威武+ 150好東西,學習了
紫夜依晨+ 3感謝分享!
dongr87+ 3很細緻,受教了!
hanzhangqin8+ 3感謝分享~
hercule24+ 3牛逼!
melodylin32+ 2膩害!辛苦吶!
KikSamuel+ 3我就只能加3分....
sanguine+ 150太贊了!!!
anonym+ 150都是版主 水平差的太多了%>_<%
rsun+ 150牛逼!細緻!
alonever+ 150
Kimurate+ 50再接再厲!
小K+ 200總評分:大米 + 1120 查看全部評分python,網頁本主題由 alonever 於 2014-2-14 05:20:51 加入精華
分享3
收藏37
好苗3
雜草0相關帖子·小米和學校上網頁說的不一樣,應該以那個為準?·還有什麼
推薦閱讀:
※html語言教程/網頁編程基礎教程
※金融網頁版直播間搭建
※網站建設—1 從擁有一個域名開始
※【問題解答】python解析網頁源代碼返回亂碼問題 | 在路上
※網站建設— 4 終於等到上傳網站內容了