国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

python爬蟲 正則表達式使用技巧及爬取個人博客的實例講解

2020-01-04 16:37:18
字體:
來源:轉載
供稿:網友

這篇博客是自己《數(shù)據挖掘與分析》課程講到正則表達式爬蟲的相關內容,主要簡單介紹Python正則表達式爬蟲,同時講述常見的正則表達式分析方法,最后通過實例爬取作者的個人博客網站。希望這篇基礎文章對您有所幫助,如果文章中存在錯誤或不足之處,還請海涵。真的太忙了,太長時間沒有寫博客了,抱歉~

一.正則表達式

正則表達式(Regular Expression,簡稱Regex或RE)又稱為正規(guī)表示法或常規(guī)表示法,常常用來檢索、替換那些符合某個模式的文本,它首先設定好了一些特殊的字及字符組合,通過組合的“規(guī)則字符串”來對表達式進行過濾,從而獲取或匹配我們想要的特定內容。它具有靈活、邏輯性和功能性非常的強,能迅速地通過表達式從字符串中找到所需信息的優(yōu)點,但對于剛接觸的人來說,比較晦澀難懂。

1.re模塊

Python通過re模塊提供對正則表達式的支持,使用正則表達式之前需要導入該庫。

import re 

import re其基本步驟是先將正則表達式的字符串形式編譯為Pattern實例,然后使用Pattern實例處理文本并獲得一個匹配(Match)實例,再使用Match實例獲得所需信息。常用的函數(shù)是findall,原型如下:

findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])

該函數(shù)表示搜索字符串string,以列表形式返回全部能匹配的子串。

其中參數(shù)re包括三個常見值:

(1)re.I(re.IGNORECASE):忽略大小寫(括號內是完整寫法)

(2)re.M(re.MULTILINE):允許多行模式

(3)re.S(re.DOTALL):支持點任意匹配模式

Pattern對象是一個編譯好的正則表達式,通過Pattern提供的一系列方法可以對文本進行匹配查找。Pattern不能直接實例化,必須使用re.compile()進行構造。

2.complie方法

re正則表達式模塊包括一些常用的操作函數(shù),比如complie()函數(shù)。其原型如下:

compile(pattern[,flags] ) 

該函數(shù)根據包含正則表達式的字符串創(chuàng)建模式對象,返回一個pattern對象。參數(shù)flags是匹配模式,可以使用按位或“|”表示同時生效,也可以在正則表達式字符串中指定。Pattern對象是不能直接實例化的,只能通過compile方法得到。

簡單舉個實例,使用正則表達式獲取字符串中的數(shù)字內容,如下所示:

>>> import re>>> string="A1.45,b5,6.45,8.82">>> regex = re.compile(r"/d+/.?/d*")>>> print regex.findall(string)['1.45', '5', '6.45', '8.82']>>> 

3.match方法

match方法是從字符串的pos下標處起開始匹配pattern,如果pattern結束時已經匹配,則返回一個Match對象;如果匹配過程中pattern無法匹配,或者匹配未結束就已到達endpos,則返回None。該方法原型如下:

match(string[, pos[, endpos]]) | re.match(pattern, string[, flags])

參數(shù)string表示字符串;pos表示下標,pos和endpos的默認值分別為0和len(string);參數(shù)flags用于編譯pattern時指定匹配模式。

4.search方法

search方法用于查找字符串中可以匹配成功的子串。從字符串的pos下標處起嘗試匹配pattern,如果pattern結束時仍可匹配,則返回一個Match對象;若無法匹配,則將pos加1后重新嘗試匹配;直到pos=endpos時仍無法匹配則返回None。 函數(shù)原型如下:

search(string[, pos[, endpos]]) | re.search(pattern, string[, flags])

參數(shù)string表示字符串;pos表示下標,pos和endpos的默認值分別為0和len(string));參數(shù)flags用于編譯pattern時指定匹配模式。

5.group和groups方法

group([group1, …])方法用于獲得一個或多個分組截獲的字符串,當它指定多個參數(shù)時將以元組形式返回。groups([default])方法以元組形式返回全部分組截獲的字符串,相當于調用group(1,2,…last)。default表示沒有截獲字符串的組以這個值替代,默認為None。

二.正則表達式抓取網絡數(shù)據常見方法

在第三小節(jié)作者將介紹常用的正則表達式抓取網絡數(shù)據的一些技巧,這些技巧都是作者自然語言處理和數(shù)據抓取實際編程中的總結,可能不是很系統(tǒng),但是也能給讀者提供一些抓取數(shù)據的思路以及解決實際的一些問題。

1.抓取標簽間的內容

HTML語言是采用標簽對的形式來編寫網站的,包括起始標簽和結束標簽,比如<head></head>、<tr></tr>、<script><script>等。下面講解抓取標簽對之間的文本內容。

(1) 抓取title標簽間的內容

首先爬取網頁的標題,采用的正則表達式為'<title>(.*?)</title>',爬取百度標題代碼如下:

# coding=utf-8 import re import urllib url = "http://www.baidu.com/" content = urllib.urlopen(url).read() print unicode(u,'utf-8')#獲取超鏈接<a>和</a>之間內容res = r'<a .*?>(.*?)</a>' texts = re.findall(res, content, re.S|re.M) for t in texts: print unicode(t,'utf-8')

輸出結果部分內容如下所示,這里如果直接輸出print u或print t可能會亂碼,需要調用函數(shù)unicode(u,'utf-8')進行轉碼。

#獲取完整超鏈接<a href="http://news.baidu.com" rel="external nofollow" rel="external nofollow" name="tj_trnews" class="mnav">新聞</a><a href="http://www.hao123.com" rel="external nofollow" rel="external nofollow" name="tj_trhao123" class="mnav">hao123</a><a href="http://map.baidu.com" rel="external nofollow" rel="external nofollow" name="tj_trmap" class="mnav">地圖</a><a href="http://v.baidu.com" rel="external nofollow" rel="external nofollow" name="tj_trvideo" class="mnav">視頻</a>...#獲取超鏈接<a>和</a>之間內容新聞hao123地圖視頻...

(3) 抓取tr/td標簽間的內容

網頁中常用的布局包括table布局或div布局,其中table表格布局中常見的標簽包括tr、th和td,表格行為tr(table row),表格數(shù)據為td(table data),表格表頭th(table heading)。那么如何抓取這些標簽之間的內容呢?下面代碼是獲取它們之間內容。

假設存在HTML代碼如下所示:

<html><head><title>表格</title></head><body> <table border=1>  <tr><th>學號</th><th>姓名</th></tr>  <tr><td>1001</td><td>楊秀璋</td></tr>  <tr><td>1002</td><td>嚴娜</td></tr> </table></body></html>

則爬取對應值的Python代碼如下:

# coding=utf-8 import re import urllibcontent = urllib.urlopen("test.html").read() #打開本地文件#獲取<tr></tr>間內容res = r'<tr>(.*?)</tr>'texts = re.findall(res, content, re.S|re.M)for m in texts: print m#獲取<th></th>間內容for m in texts: res_th = r'<th>(.*?)</th>' m_th = re.findall(res_th, m, re.S|re.M) for t in m_th:  print t#直接獲取<td></td>間內容res = r'<td>(.*?)</td><td>(.*?)</td>' texts = re.findall(res, content, re.S|re.M)for m in texts: print m[0],m[1]

輸出結果如下,首先獲取tr之間的內容,然后再在tr之間內容中獲取<th>和</th>之間值,即“學號”、“姓名”,最后講述直接獲取兩個<td>之間的內容方法。

>>> <th>學號</th><th>姓名</th><td>1001</td><td>楊秀璋</td><td>1002</td><td>嚴娜</td>學號姓名1001 楊秀璋1002 嚴娜>>>

2.抓取標簽中的參數(shù)

(1) 抓取超鏈接標簽的URL

HTML超鏈接的基本格式為“<a href=URL>鏈接內容</a>”,現(xiàn)在需要獲取其中的URL鏈接地址,方法如下:

# coding=utf-8 import recontent = '''<a href="http://news.baidu.com" rel="external nofollow" rel="external nofollow" name="tj_trnews" class="mnav">新聞</a><a href="http://www.hao123.com" rel="external nofollow" rel="external nofollow" name="tj_trhao123" class="mnav">hao123</a><a href="http://map.baidu.com" rel="external nofollow" rel="external nofollow" name="tj_trmap" class="mnav">地圖</a><a href="http://v.baidu.com" rel="external nofollow" rel="external nofollow" name="tj_trvideo" class="mnav">視頻</a>'''res = r"(?<=href=/").+?(?=/")|(?<=href=/').+?(?=/')"urls = re.findall(res, content, re.I|re.S|re.M)for url in urls: print url 

輸出內容如下:

>>> http://news.baidu.comhttp://www.hao123.comhttp://map.baidu.comhttp://v.baidu.com>>> 

(2) 抓取圖片超鏈接標簽的URL

HTML插入圖片使用標簽的基本格式為“<img src=圖片地址 />”,則需要獲取圖片URL鏈接地址的方法如下:

content = '''<img   #重點點位置infobox = text[start:end] print infobox 

同時爬取過程中可能會爬取到無關變量,此時需要對無關內容進行過濾,這里推薦使用replace函數(shù)和正則表達式進行處理。比如,爬取內容如下:

# coding=utf-8 import recontent = '''<tr><td>1001</td><td>楊秀璋<br /></td></tr><tr><td>1002</td><td>顏 娜</td></tr><tr><td>1003</td><td><B>Python</B></td></tr>'''res = r'<td>(.*?)</td><td>(.*?)</td>' texts = re.findall(res, content, re.S|re.M)for m in texts: print m[0],m[1]

輸出如下所示:

>>> 1001 楊秀璋<br />1002 顏 娜1003 <B>Python</B>>>> 

此時需要過濾多余字符串,如換行(<br />)、空格( )、加粗(<B></B>)。

過濾代碼如下:

# coding=utf-8 import recontent = '''<tr><td>1001</td><td>楊秀璋<br /></td></tr><tr><td>1002</td><td>顏 娜</td></tr><tr><td>1003</td><td><B>Python</B></td></tr>'''res = r'<td>(.*?)</td><td>(.*?)</td>' texts = re.findall(res, content, re.S|re.M)for m in texts: value0 = m[0].replace('<br />', '').replace(' ', '') value1 = m[1].replace('<br />', '').replace(' ', '') if '<B>' in value1:  m_value = re.findall(r'<B>(.*?)</B>', value1, re.S|re.M)  print value0, m_value[0] else:  print value0, value1

采用replace將字符串“<br />”或“' ”替換成空白,實現(xiàn)過濾,而加粗(<B></B>)需要使用正則表達式過濾,輸出結果如下:

>>> 1001 楊秀璋1002 顏娜1003 Python>>> 

三.實戰(zhàn)爬取個人博客實例

在講述了正則表達式、常用網絡數(shù)據爬取模塊、正則表達式爬取數(shù)據常見方法等內容之后,我們將講述一個簡單的正則表達式爬取網站的實例。這里作者用正則表達式爬取作者的個人博客網站的簡單示例,獲取所需內容。

作者的個人網址“http://www.eastmountyxz.com/”打開如下圖所示。

python,爬蟲,正則表達式

假設現(xiàn)在需要爬取的內容如下:

1.博客網址的標題(title)內容。

2.爬取所有圖片的超鏈接,比如爬取<img src=”xxx.jpg” />中的“xxx.jpg”。

3.分別爬取博客首頁中的四篇文章的標題、超鏈接及摘要內容,比如標題為“再見北理工:憶北京研究生的編程時光”。

1.分析過程

第一步 瀏覽器源碼定位

首先通過瀏覽器定位這些元素源代碼,發(fā)現(xiàn)它們之間的規(guī)律,這稱為DOM樹文檔節(jié)點樹分析,找到所需爬取節(jié)點對應的屬性和屬性值,如圖3.6所示。

python,爬蟲,正則表達式

標題“再見北理工:憶北京研究生的編程時光”位于<div class=”essay”></div>節(jié)點下,它包括一個<h1></h1>記錄標題,一個<p></p>記錄摘要信息,即:

<div class="essay"><h1 style="text-align:center"><a href="http://blog.csdn.net/eastmount/.../52201984" rel="external nofollow" >再見北理工:憶北京研究生的編程時光</a></h1><p style="text-indent: 2em;"> 兩年前,我本科畢業(yè)寫了這樣一篇文章:《 回憶自己的大學四年得與失 》,感慨了自己在北理軟院四年的所得所失;兩年后,我離開了帝都,回到了貴州家鄉(xiāng),準備開啟一段新的教師生涯,在此也寫一篇文章紀念下吧!還是那句話:這篇文章是寫給自己的,希望很多年之后,回想起自己北京的六年時光,也是美好的回憶。文章可能有點長,但希望大家像讀小說一樣耐心品讀,....</p></div>

其余三篇文章同樣為<div class=”essay1”></div>、
<div class=”essay2”></div>和<div class=”essay3”></div>。

第二步 正則表達式爬取標題

網站的標題通常位于<head><title>...</title></head>之間,爬取博客網站的標題“秀璋學習天地”的方法是通過正則表達式“<title>(.*?)</title>”實現(xiàn),代碼如下,首先通過urlopen()函數(shù)訪問博客網址,然后定義正則表達式爬取。如下圖所示:

python,爬蟲,正則表達式

第三步 正則表達式爬取所有圖片地址

由于HTML插入圖片標簽格式為“<img src=圖片地址 />”,則使用正則表達式獲取圖片URL鏈接地址的方法如下,獲取以“src=”開頭,以雙引號結尾的內容即可。

import reimport urlliburl = "http://www.eastmountyxz.com/"content = urllib.urlopen(url).read()urls = re.findall(r'src="(.*?)"', content)for url in urls: print url

輸出共顯示了6張圖片,但每張圖片省略了博客地址“http://www.eastmountyxz.com/”,增加相關地址則可以通過瀏覽器訪問,如“http://www.eastmountyxz.com/images/11.gif”。

第四步 正則表達式爬取博客內容

前面第一步講述了如何定位四篇文章的標題,第一篇文章位于<div class=”essay”>和</div>標簽之間,第二篇位于<div class=”essay1”>和</div>,依次類推。但是該HTML代碼存在一個錯誤:class屬性通常表示一類標簽,它們的值都應該是相同的,所以這四篇文章的class屬性都應該是“essay”,而name或id可以用來標識其唯一值。

這里使用find()函數(shù)定位<div class=”essay”>開頭,</div>結尾,獲取它們之間的值。比如獲取第一篇文章的標題和超鏈接代碼如下:

import reimport urlliburl = "http://www.eastmountyxz.com/"content = urllib.urlopen(url).read()start = content.find(r'<div class="essay">')end = content.find(r'<div class="essay1">')print content[start:end]

該部分代碼分為三步驟:

(1) 調用urllib庫的urlopen()函數(shù)打開博客地址,并讀取內容賦值給content變量。

(2) 調用find()函數(shù)查找特定的內容,比如class屬性為“essay”的div標簽,依次定位獲取開始和結束的位置。

(3) 進行下一步分析,獲取源碼中的超鏈接和標題等內容。

定位這段內容之后,再通過正則表達式獲取具體內容,代碼如下:

import reimport urlliburl = "http://www.eastmountyxz.com/"content = urllib.urlopen(url).read()start = content.find(r'<div class="essay">')end = content.find(r'<div class="essay1">')page = content[start:end]     res = r"(?<=href=/").+?(?=/")|(?<=href=/').+?(?=/')"t1 = re.findall(res, page) #超鏈接print t1[0]t2 = re.findall(r'<a .*?>(.*?)</a>', page) #標題print t2[0]t3 = re.findall('<p style=.*?>(.*?)</p>', page, re.M|re.S) #摘要(print t3[0]

調用正則表達式分別獲取內容,由于爬取的段落(P)存在換行內容,所以需要加入re.M和re.S支持換行查找,最后輸出結果如下:

>>> http://blog.csdn.net/eastmount/article/details/52201984再見北理工:憶北京研究生的編程時光 兩年前,我本科畢業(yè)寫了這樣一篇文章:《 回憶自己的大學四年得與失 》,感慨了自己在北理軟院四年的所得所失;兩年后,我離開了帝都,回到了貴州家鄉(xiāng),準備開啟一段新的教師生涯,在此也寫一篇文章紀念下吧!  還是那句話:這篇文章是寫給自己的,希望很多年之后,回想起自己北京的六年時光,也是美好的回憶。文章可能有點長,但希望大家像讀小說一樣耐心品讀,....>>> 

2.代碼實現(xiàn)

完整代碼參考test03_10.py文件,代碼如下所示。

#coding:utf-8import reimport urlliburl = "http://www.eastmountyxz.com/"content = urllib.urlopen(url).read()#爬取標題title = re.findall(r'<title>(.*?)</title>', content)print title[0]#爬取圖片地址urls = re.findall(r'src="(.*?)"', content)for url in urls: print url#爬取內容start = content.find(r'<div class="essay">')end = content.find(r'<div class="essay1">')page = content[start:end]   res = r"(?<=href=/").+?(?=/")|(?<=href=/').+?(?=/')"t1 = re.findall(res, page) #超鏈接print t1[0]t2 = re.findall(r'<a .*?>(.*?)</a>', page) #標題print t2[0]t3 = re.findall('<p style=.*?>(.*?)</p>', page, re.M|re.S) #摘要(print t3[0]print ''start = content.find(r'<div class="essay1">')end = content.find(r'<div class="essay2">')page = content[start:end]   res = r"(?<=href=/").+?(?=/")|(?<=href=/').+?(?=/')"t1 = re.findall(res, page) #超鏈接print t1[0]t2 = re.findall(r'<a .*?>(.*?)</a>', page) #標題print t2[0]t3 = re.findall('<p style=.*?>(.*?)</p>', page, re.M|re.S) #摘要(print t3[0]

輸出結果如圖所示。

python,爬蟲,正則表達式

通過上面的代碼,讀者會發(fā)現(xiàn)使用正則表達式爬取網站還是比較繁瑣,尤其是定位網頁節(jié)點時,后面將講述Python提供的常用第三方擴展包,利用這些包的函數(shù)進行定向爬取。

希望這篇文字對你有所幫助,尤其是剛接觸爬蟲的同學或是遇到類似問題的同學,更推薦大家使用BeautifulSoup、Selenium、Scrapy等庫來爬取數(shù)據。

以上這篇python爬蟲 正則表達式使用技巧及爬取個人博客的實例講解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到python教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 柳江县| 镇雄县| 包头市| 日照市| 西峡县| 鹤峰县| 威海市| 霍城县| 文成县| 齐齐哈尔市| 沁阳市| 西峡县| 瑞金市| 南投县| 灵丘县| 沭阳县| 溧水县| 辽宁省| 长子县| 明溪县| 玉环县| 石景山区| 青冈县| 太原市| 两当县| 遂川县| 明水县| 拜泉县| 永德县| 类乌齐县| 肇庆市| 大洼县| 来安县| 和林格尔县| 石棉县| 同心县| 中江县| 怀来县| 临清市| 读书| 阿拉善盟|