[python] 常用正則表達式爬取網頁信息及分析HTML標籤總結
Linux編程
點擊右側關注,免費入門到精通!
作者丨Eastmount
https://blog.csdn.net/Eastmount/article/details/51082253
這篇文章主要是介紹Python爬取網頁信息時,經常使用的正則表達式及方法。它是一篇總結性文章,實用性比較大,主要解決自己遇到的爬蟲問題,也希望對你有所幫助~
當然如果會Selenium基於自動化測試爬蟲、BeautifulSoup分析網頁DOM節點,這就更方便了,但本文更多的是介紹基於正則的底層爬取分析。
涉及內容如下:
常用正則表達式爬取網頁信息及HTML分析總結
1.獲取<tr></tr>標籤之間內容
2.獲取<a href..></a>超鏈接之間內容
3.獲取URL最後一個參數命名圖片或傳遞參數
4.爬取網頁中所有URL鏈接
5.爬取網頁標題title兩種方法
6.定位table位置並爬取屬性-屬性值
7.過濾<span></span>等標籤
8.獲取<script></script>等標籤內容
9.通過replace函數過濾<br />標籤
10.獲取<img ../>中超鏈接及過濾<img>標籤
1.獲取<tr></tr>標籤之間內容
該部分主要是通過正則表達式獲取兩個標籤之間的內容,通常這種標籤都是成對出現的。
開始標籤如:<tr>、<th>、<td>、<a>、<table>、<div>...
後綴標籤如:</tr>、</th>、</td>、</a>、</table>、</div>...
核心代碼:
res_tr = r"<tr>(.*?)</tr>"
m_tr = re.findall(res_tr,language,re.S|re.M)
例子:
# coding=utf-8 import
language =
"""<tr><th>性別:</th><td>男</td></tr><tr>"""
#正則表達式獲取<tr></tr>之間內容
res_tr =
r"<tr>(.*?)</tr>"
m_tr = re.findall(res_tr,language,re.S|re.M)
for
linein
m_tr:#獲取表格第一列th 屬性
res_th =
r"<th>(.*?)</th>"
m_th = re.findall(res_th,line,re.S|re.M)
for
mmin
m_th:"utf-8"
),#unicode防止亂
#獲取表格第二列td 屬性值
res_td =
r"<td>(.*?)</td>"
m_td = re.findall(res_td,line,re.S|re.M)
for
nnin
m_td:"utf-8"
)輸出如下所示:
>> /th><td>男</td >>
<th>性別:<
性別: 男
python通過re模塊提供對正則表達式的支持。使用re的一般步驟是先將正則表達式的字元串形式編譯為Pattern實例,然後使用Pattern實例處理文本並獲得匹配結果(一個Match實例),最後使用Match實例獲得信息,進行其他的操作。
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]): 搜索string,以列表形式返回全部能匹配的子串。其中RE的常見參數包括:
re.I(re.IGNORECASE): 忽略大小寫(括弧內是完整寫法)
re.M(re.MULTILINE): 多行模式,改變"^"和"$"的行為
re.S(re.DOTALL): 點任意匹配模式,改變"."的行為
2.獲取超鏈接<a href=..></a>之間內容
通常在使用正則表達式時,需要分析網頁鏈接,獲取URL或網頁內容。核心代碼如下:
res = r"<a .*?>(.*?)</a>"
mm = re.findall(res, content, re.S|re.M)
urls=re.findall(r"<a.*?href=.*?</a>", content, re.I|re.S|re.M)
例子:
# coding=utf-8 import
content =
"""
<td>
<a href="https://www.baidu.com/articles/zj.html" title="浙江省">浙江省主題介紹</a>
<a href="https://www.baidu.com//articles/gz.html" title="貴州省">貴州省主題介紹</a>
</td>
"""
#獲取<a href></a>之間的內容
u"獲取鏈接文本內容:"
res =
r"<a .*?>(.*?)</a>"
mm = re.findall(
res, content, re.S|re.M)
for
valuein
mm:#獲取所有<a href></a>鏈接所有內容
u"
獲取完整鏈接內容:"
urls=re.findall(
r"<a.*?href=.*?</a>"
, content, re.I|re.S|re.M)for
iin
urls:#獲取<a href></a>中的URL
u"
獲取鏈接中URL:"
res_url =
r"(?<=href=").+?(?=")|(?<=href=").+?(?=")"
link = re.findall(res_url , content, re.I|re.S|re.M)
for
urlin
link:輸出如下圖所示:
獲取鏈接文本內容:>>>
浙江省主題介紹
貴州省主題介紹
獲取完整鏈接內容:
<a href=
"https://www.baidu.com/articles/zj.html"
title="浙江省"
>浙江省主題介紹</a><a href=
"https://www.baidu.com//articles/gz.html"
title="貴州省"
>貴州省主題介紹</a>獲取鏈接中URL:
https://www.baidu.com/articles/zj.html
https://www.baidu.com//articles/gz.html
>>>
當然如果是通過Selenium分析DOM樹結構獲取href對應的url或title中的值,其核心代碼如下所示,這裡主要是給大家做個對比,理解不同方法的優勢:
driver.get(link)
elem = driver.find_elements_by_xpath("//div[@class="piclist"]/tr/dd[1]")
for url in elem:
pic_url = url.get_attribute("href")
print pic_url
參考文章:
https://blog.csdn.net/eastmount/article/details/49393483
3.獲取URL最後一個參數命名圖片或傳遞參數
通常在使用Python爬取圖片過程中,會遇到圖片對應的URL最後一個欄位通常用於命名圖片,如虎撲孫悅妻子圖片:
//i1.hoopchina.com.cn/blogfile/201411/11/BbsImg141568417848931_640*640.jpg
此時需要通過該URL的"/"後面的參數命名圖片,則方法如下:
"//i1.hoopchina.com.cn/blogfile/201411/11/BbsImg141568417848931_640*640.jpg" values split "/" 1 print valuesurls =
輸出如下所示:
>> 0 640 >>
BbsImg141568417848931_64
在使用Python獲取GET方法的URL鏈接中,還可能存在傳遞參數的值。
此時獲取參數方法如下:
"http://localhost/test.py?a=hello&b=world" values split "?" 1 print values for split "&" print split "="url =
!
輸出如下所示:
>> "a" "hello" "b" "world" >>
a=hello&b=world
[
[
4.爬取網頁中所有URL鏈接
在學習爬蟲過程中,你肯定需要從固有網頁中爬取URL鏈接,再進行下一步的循環爬取或URL抓取。如下,爬取CSDN首頁的所有URL鏈接。
# coding=utf-8 import import
url =
"http://www.csdn.net/"
content = urllib.urlopen(url).read()
urls = re.findall(
r"<a.*?href=.*?</a>"
, content, re.I)for
urlin
urls:"utf-8"
)link_list = re.findall(
r"(?<=href=").+?(?=")|(?<=href=").+?(?=")"
, content)for
urlin
link_list:輸出如下所示:
< a href "https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn">>>
</
a
><
a
href
="http://passport.csdn.net/account/mobileregister?action=mobileRegister"
>註冊</
a
><
a
href
="https://passport.csdn.net/help/faq"
>幫助</
a
>...
https://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn
http://passport.csdn.net/account/mobileregister?action=mobileRegister
https://passport.csdn.net/help/faq
...
>>>
5.爬取網頁標題title兩種方法
獲取網頁標題也是一種常見的爬蟲,如我在爬取維基百科國家信息時,就需要爬取網頁title。通常位於<html><head><title>標題</title></head></html>中。
下面是爬取CSDN標題的兩種方法介紹:
# coding=utf-8 import import
url =
"http://www.csdn.net/"
content = urllib.urlopen(url).read()
u"方法一:"
title_pat =
r"(?<=<title>).*?(?=</title>)"
title_ex = re.compile(title_pat,re.M|re.S)
title_obj = re.search(title_ex, content)
title = title_obj.group()
u"方法二:"
title = re.findall(
r"<title>(.*?)</title>"
, content)0
]輸出如下所示:
>> >>
方法一:
CSDN.NET - 全球最大中文IT社區,為IT專業技術人員提供最全面的信息傳播和服務平台
方法二:
CSDN.NET - 全球最大中文IT社區,為IT專業技術人員提供最全面的信息傳播和服務平台
6.定位table位置並爬取屬性-屬性值
如果使用Python庫的一些爬取,通常可以通過DOM樹結構進行定位,如代碼:
login = driver.find_element_by_xpath("//form[@id="loginForm"]")
參考文章:
https://blog.csdn.net/eastmount/article/details/47825633
但如果是正則表達式這種相對傳統傻瓜式的方法,通過通過find函數尋找指定table方法進行定位。如:獲取Infobox的table信息。
通過分析源代碼發現「程序設計語言列表」的消息盒如下:
<table class="infobox vevent" ..><tr><th></th><td></td></tr></table>
r"<table class="infobox vevent"" #起點記錄查詢位置 r"</table>" printstart = content.find(
end = content.find(
infobox = language[start:end]
print infobox 輸出其中一門語言ActionScript的InfoBox消息盒部分源代碼如下:
< table class "infobox vevent" cellspacing "3" style "border-spacing:3px;width:22em;text-align:left;font-size:small;line-height:1.5em;"
<
caption
class
="summary"
><b
>ActionScript</
b
></caption
><
tr
><
th
scope
="row"
style
="text-align:left;white-space:nowrap;;;"
>發行時間</
th
><
td
style
=";;"
>1998年</
td
></
tr
><
tr
><
th
scope
="row"
style
="text-align:left;white-space:nowrap;;;"
>實現者</
th
><
td
class
="organiser"
style
=";;"
><a
href
="/wiki/Adobe_Systems"
title
="Adobe Systems"
>Adobe Systems</
a
></td
></
tr
><
tr
><
tr
><
th
scope
="row"
style
="text-align:left;white-space:nowrap;;;"
>啟發語言</
th
><
td
style
=";;"
><a
href
="/wiki/JavaScript"
title
="JavaScript"
>JavaScript</
a
>、<
a
href
="/wiki/Java"
title
="Java"
>Java</
a
></td
></
tr
></
table
>參考文章:
https://blog.csdn.net/eastmount/article/details/44342559
然後再在這個infobox內容中通過正則表達式進行分析爬取。下面講述爬取屬性-屬性值:
爬取格式如下:
<table>
<tr>
<th>屬性</th>
<td>屬性值</td>
</tr>
</table>
其中th表示加粗處理,td和th中可能存在屬性如title、id、type等值;同時<td></td>之間的內容可能存在<a href=..></a>或<span></span>或<br />等值,都需要處理。下面先講解正則表達式獲取td值的例子:
參考:http://bbs.csdn.net/topics/390353859?page=1
< table
<
tr
><
td
>序列號</
td
><td
>DEIN3-39CD3-2093J3</
td
><
td
>日期</
td
><td
>2013年1月22日</
td
><
td
>售價</
td
><td
>392.70 元</
td
><
td
>說明</
td
><td
>僅限5用戶使用</
td
></
tr
></
table
>Python代碼如下:
# coding=utf-8 import
s =
"""<table>
<tr>
<td>序列號</td><td>DEIN3-39CD3-2093J3</td>
<td>日期</td><td>2013年1月22日</td>
<td>售價</td><td>392.70 元</td>
<td>說明</td><td>僅限5用戶使用</td>
</tr>
</table>
"""
res =
r"<td>(.*?)</td><td>(.*?)</td>"
m = re.findall(res,s,re.S|re.M)
for
linein
m:0
],"utf-8"
),unicode(line[1
],"utf-8"
)#unicode防止亂碼
#輸出結果如下:
#序列號 DEIN3-39CD3-2093J3
#日期 2013年1月22日
#售價 392.70 元
#說明 僅限5用戶使用
如果<td id="">包含該屬性則正則表達式為r"<td id=.*?>(.*?)</td>";同樣如果不一定是id屬性開頭,則可以使用正則表達式r"<td .*?>(.*?)</td>"。
7.過濾<span></span>等標籤
在獲取值過程中,通常會存在<span>、<br>、<a href>等標籤,下面舉個例子過濾。
<td><span class="nickname">(字) 翔宇</span></td>過濾標籤<span>核心代碼:
elif "span" in nn: #處理標籤<span>
res_value = r"<span .*?>(.*?)</span>"
m_value = re.findall(res_value,nn,re.S|re.M)
for value in m_value:
print unicode(value,"utf-8"),
代碼如下,注意print中逗號連接字元串:
# coding=utf-8 import
language =
"""
<table class="infobox bordered vcard" style_="width: 21em; font-size: 89%; text-align: left;" cellpadding="3">
<caption style_="text-align: center; font-size: larger;" class="fn"><b>周恩來</b></caption>
<tr>
<th>性別:</th>
<td>男</td>d
</tr>
<tr>
<th>異名:</th>
<td><span class="nickname">(字) 翔宇</span></td>
</tr>
<tr>
<th>政黨:</th>
<td><span class="org"><a href="../articles/%E4%B8%AD9A.html" title="中國共產黨">中國共產黨</a></span></td>
</tr>
<tr>
<th>籍貫:</th>
<td><a href="../articles/%E6%B5%9981.html" title="浙江省">浙江省</a><a href="../articles/%E7%BB%8D82.html" title="紹興市">紹興市</a></td>
</tr>
</table>
"""
#獲取table中tr值
res_tr =
r"<tr>(.*?)</tr>"
m_tr = re.findall(res_tr,language,re.S|re.M)
for
linein
m_tr:#獲取表格第一列th 屬性
res_th =
r"<th>(.*?)</th>"
m_th = re.findall(res_th,line,re.S|re.M)
for
mmin
m_th:if
"href"
in
mm:#如果獲取加粗的th中含超鏈接則處理
restr =
r"<a href=.*?>(.*?)</a>"
h = re.findall(restr,mm,re.S|re.M)
0
],"utf-8"
),#逗號連接屬性值 防止換行
else
:"utf-8"
),#unicode防止亂
#獲取表格第二列td 屬性值
res_td =
r"<td>(.*?)</td>"
#r"<td .*?>(.*?)</td>"
m_td = re.findall(res_td,line,re.S|re.M)
for
nnin
m_td:if
"href"
in
nn:#處理超鏈接<a href=../rel=..></a>
res_value =
r"<a .*?>(.*?)</a>"
m_value = re.findall(res_value,nn,re.S|re.M)
for
valuein
m_value:"utf-8"
),elif
"span"
in
nn:#處理標籤<span>
res_value =
r"<span .*?>(.*?)</span>"
m_value = re.findall(res_value,nn,re.S|re.M)
#<td><span class="nickname">(字) 翔宇</span></td>
for
valuein
m_value:"utf-8"
),else
:"utf-8"
)," "
#換行
輸出如下所示:
>> >>
性別: 男
異名: (字) 翔宇
政黨: 中國共產黨
籍貫: 浙江省 紹興市
8.獲取<script></script>等標籤內容
比如在獲取游訊網圖庫中,圖集對應的原圖它是存儲在script中,其中獲取原圖-original即可,縮略圖-thumb,大圖-big,通過正則表達式下載URL:
res_original = r""original":"(.*?)"" #原圖
m_original = re.findall(res_original,script)
代碼如下:
# coding=utf-8 import import
content =
"""
<script>var images = [
{ "big":"//i-2.yxdown.com/2015/3/18/KDkwMHgp/6381ccc0-ed65-4422-8671-b3158d6ad23e.jpg",
"thumb":"//i-2.yxdown.com/2015/3/18/KHgxMjAp/6381ccc0-ed65-4422-8671-b3158d6ad23e.jpg",
"original":"//i-2.yxdown.com/2015/3/18/6381ccc0-ed65-4422-8671-b3158d6ad23e.jpg",
"title":"","descript":"","id":75109},
{ "big":"//i-2.yxdown.com/2015/3/18/KDkwMHgp/fec26de9-8727-424a-b272-f2827669a320.jpg",
"thumb":"//i-2.yxdown.com/2015/3/18/KHgxMjAp/fec26de9-8727-424a-b272-f2827669a320.jpg",
"original":"//i-2.yxdown.com/2015/3/18/fec26de9-8727-424a-b272-f2827669a320.jpg",
"title":"","descript":"","id":75110},
</script>
"""
html_script =
r"<script>(.*?)</script>"
m_script = re.findall(html_script,content,re.S|re.M)
for
scriptin
m_script:res_original =
r""original":"(.*?)""
#原圖
m_original = re.findall(res_original,script)
for
pic_urlin
m_original:filename = os.path.basename(pic_url)
#去掉目錄路徑,返迴文件名
urllib.urlretrieve(pic_url,
"E:\"
+filename)#下載圖片
運行結果如下圖所示,同時下載圖片至E盤。
參考文章:
https://blog.csdn.net/eastmount/article/details/44492787
9.通過replace過濾<br />標籤
在獲取值過程中,通常會存<br />標籤,它表示HTML換行的意思。常用的方法可以通過標籤"<"和">"進行過濾,但是這裡我想講述的是一種Python常用的過濾方法,在處理中文亂碼或一些特殊字元時,可以使用函數replace過濾掉這些字元。核心代碼如下:
if "<br />" in value:
value = value.replace("<br />","") #過濾該標籤
value = value.replace("
"," ") #換行空格替代 否則總換行
例如過濾前後的例子:
達洪阿 異名: (字) 厚菴<br /> (諡) 武壯<br /> (勇號) 阿克達春巴圖魯
達洪阿 異名: (字) 厚菴 (諡) 武壯 (勇號) 阿克達春巴圖魯
10.獲取<img ../>中超鏈接及過濾<img>標籤
在獲取值屬性值過程中,可能在分析table/tr/th/td標籤後,仍然存在<img />圖片鏈接,此時在獲取文字內容時,你可能需要過濾掉這些<img>標籤。這裡採用的方法如下:
value = re.sub("<[^>]+>","", value)
例如:
#encoding:utf-8
import os
import re
value = """
<
table
class
="infobox"
style
="width: 21em; text-align: left;"
cellpadding
="3"
><
tr
bgcolor
="#CDDBE8"
><
th
colspan
="2"
><
center
class
="role"
><b
>中華民國政治人士</
b
><br
/></center
></
th
></
tr
><
tr
><
th
>性別:</
th
><
td
>男</
td
></
tr
><
tr
><
th
>政黨:</
th
><
td
><span
class
="org"
><
img
alt
="中國國民黨"
src
="../../../../images/Kuomintang.svg.png"
width
="19"
height
="19"
border
="0"
/><
a
href
="../../../../articles/%8B%E6%B0%91%E9%BB%A8.html"
title
="中國國民黨"
>中國國民黨</
a
></span
></td
></
tr
></
table
>"""
value = re.sub("
<
[^
>]+>","", value) #過濾HTML標籤print value
輸出如下:
>>
中華民國政治人士
性別:
男
政黨:
中國國民黨
>>
>雖然僅僅包括漢字,但是中間會存在換行,需要過濾<br />即可:
if "<br />" in value value value "<br />" "" value value " " " value "<[^>]+>" "" value #過濾HTML標籤 value
"
print
#輸出僅僅一行如下:
#中華民國政治人士 性別: 男 政黨: 中國國民黨
下面講述第二部分,通過正則表達式獲取<img>中的src超鏈接,代碼如下:
"""<img alt="中國國民黨" src="../images/Kuomintang.png" width="19" height="19" border="0" />""" print "src="(.*?)""test =
輸出如下所示:
>> "../images/Kuomintang.png" >>
[
findall函數返回的總是正則表達式在字元串中所有匹配結果的列表,即findall中返回列表中每個元素包含的信息。
最後希望文章對你有所幫助,後面如果遇到新的相關知識,我也會即使的更新添加的。
推薦↓↓↓
長
按
關
注
??
【
16個技術公眾號
】都在這裡!
涵蓋:程序員大咖、源碼共讀、程序員共讀、數據結構與演算法、黑客技術和網路安全、大數據科技、編程前端、Java、Python、Web編程開發、Android、iOS開發、Linux、資料庫研發、幽默程序員等。
※告訴你什麼叫憑本事單身!!!
※看到沒有,這就是妹子沒男朋友的後果
TAG:Python開發 |