當前位置:
首頁 > 知識 > [python] 常用正則表達式爬取網頁信息及分析HTML標籤總結

[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

 re

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

 line 

in

 m_tr:
    

print

 line
    

#獲取表格第一列th 屬性


    res_th = 

r"<th>(.*?)</th>"

  
    m_th = re.findall(res_th,line,re.S|re.M)
    

for

 mm 

in

 m_th:
        

print

 unicode(mm,

"utf-8"

),  

#unicode防止亂


    

#獲取表格第二列td 屬性值


    res_td = 

r"<td>(.*?)</td>"


    m_td = re.findall(res_td,line,re.S|re.M)
    

for

 nn 

in

 m_td:
        

print

 unicode(nn,

"utf-8"

)




輸出如下所示:




>>


<th>性別:<

/th><td>男</td

>
性別: 男

>>

>




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

 re

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>之間的內容


print

 

u"獲取鏈接文本內容:"


res = 

r"<a .*?>(.*?)</a>"


mm =  re.findall(
res, content, re.S|re.M)

for

 value 

in

 mm:
    

print

 value

#獲取所有<a href></a>鏈接所有內容


print

 

u"
獲取完整鏈接內容:"


urls=re.findall(

r"<a.*?href=.*?</a>"

, content, re.I|re.S|re.M)

for

 i 

in

 urls:
    

print

 i

#獲取<a href></a>中的URL


print

 

u"
獲取鏈接中URL:"


res_url = 

r"(?<=href=").+?(?=")|(?<=href=").+?(?=")"


link = re.findall(res_url ,  content, re.I|re.S|re.M)

for

 url 

in

 link:
    

print

 url




輸出如下圖所示:




>>> 

獲取鏈接文本內容:


浙江省主題介紹
貴州省主題介紹

獲取完整鏈接內容:


<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的"/"後面的參數命名圖片,則方法如下:




urls = 

"//i1.hoopchina.com.cn/blogfile/201411/11/BbsImg141568417848931_640*640.jpg"


values

 = urls.

split

(

"/"

)[-

1

]

print

 

values





輸出如下所示:




>>


BbsImg141568417848931_64

0

*

640

.jpg

>>

>




在使用Python獲取GET方法的URL鏈接中,還可能存在傳遞參數的值。


此時獲取參數方法如下:




url = 

"http://localhost/test.py?a=hello&b=world"

  

values

 = url.

split

(

"?"

)[-

1

]  

print

 

values

  

for

 key_value in values.

split

(

"&"

):
    

print

 key_value.

split

(

"="

)




輸出如下所示:




>>


a=hello&b=world
[

"a"

"hello"

]
[

"b"

"world"

]

>>

>




4.爬取網頁中所有URL鏈接




在學習爬蟲過程中,你肯定需要從固有網頁中爬取URL鏈接,再進行下一步的循環爬取或URL抓取。如下,爬取CSDN首頁的所有URL鏈接。




# coding=utf-8


import

 re

import

 urllib

url = 

"http://www.csdn.net/"


content = urllib.urlopen(url).read()
urls = re.findall(

r"<a.*?href=.*?</a>"

, content, re.I)

for

 url 

in

 urls:
    

print

 unicode(url,

"utf-8"

)

link_list = re.findall(

r"(?<=href=").+?(?=")|(?<=href=").+?(?=")"

, content)

for

 url 

in

 link_list:  
    

print

 url




輸出如下所示:




>>> 

<

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

 re

import

 urllib

url = 

"http://www.csdn.net/"


content = urllib.urlopen(url).read()

print

 

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()

print

 title

print

 

u"方法二:"


title = re.findall(

r"<title>(.*?)</title>"

, content)

print

 title[

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>




start = content.find(

r"<table class="infobox vevent""

#起點記錄查詢位置  


end = content.find(

r"</table>"

)      
infobox = language[start:end]  

print

 infobox




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

 re

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

 line 

in

 m:  
    

print

 unicode(line[

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

 re

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

 line 

in

 m_tr:
    

#獲取表格第一列th 屬性


    res_th = 

r"<th>(.*?)</th>"

   
    m_th = re.findall(res_th,line,re.S|re.M)
    

for

 mm 

in

 m_th:
        

if

 

"href"

 

in

 mm: 

#如果獲取加粗的th中含超鏈接則處理


            restr = 

r"<a href=.*?>(.*?)</a>"


            h = re.findall(restr,mm,re.S|re.M)
            

print

 unicode(h[

0

],

"utf-8"

), 

#逗號連接屬性值 防止換行


        

else

:
            

print

 unicode(mm,

"utf-8"

),   

#unicode防止亂

    

#獲取表格第二列td 屬性值


    res_td = 

r"<td>(.*?)</td>"

  

#r"<td .*?>(.*?)</td>"


    m_td = re.findall(res_td,line,re.S|re.M)
    

for

 nn 

in

 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

 value 

in

 m_value:
                

print

 unicode(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

 value 

in

 m_value:
                

print

 unicode(value,

"utf-8"

),
        

else

:
            

print

 unicode(nn,

"utf-8"

),
        

print

 

" "

 

#換行





輸出如下所示:




>>


性別: 男  
異名: (字) 翔宇  
政黨: 中國共產黨  
籍貫: 浙江省 紹興市  

>>

>




8.獲取<script></script>等標籤內容




比如在獲取游訊網圖庫中,圖集對應的原圖它是存儲在script中,其中獲取原圖-original即可,縮略圖-thumb,大圖-big,通過正則表達式下載URL:




        res_original = r""original":"(.*?)"" #原圖




        m_original = re.findall(res_original,script)




代碼如下:




# coding=utf-8


import

 re

import

 os 

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

 script 

in

 m_script:
    res_original = 

r""original":"(.*?)""

 

#原圖


    m_original = re.findall(res_original,script)
    

for

 pic_url 

in

 m_original:
        

print

 pic_url
        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

.replace(

"<br />"

,

""

)
    

value

 = 

value

.replace(

"
"

,

" "

)

value

 = re.sub(

"<[^>]+>"

,

""

value

#過濾HTML標籤


print 

value

#輸出僅僅一行如下: 


#中華民國政治人士    性別: 男   政黨:   中國國民黨 





下面講述第二部分,通過正則表達式獲取<img>中的src超鏈接,代碼如下:




test = 

"""<img alt="中國國民黨" src="../images/Kuomintang.png" width="19" height="19" border="0" />"""


print

 re.findall(

"src="(.*?)""

,test) 




輸出如下所示:




>>

>    
[

"../images/Kuomintang.png"

]

>>

>




findall函數返回的總是正則表達式在字元串中所有匹配結果的列表,即findall中返回列表中每個元素包含的信息。




最後希望文章對你有所幫助,後面如果遇到新的相關知識,我也會即使的更新添加的。




 推薦↓↓↓ 






??

16個技術公眾號

】都在這裡!


涵蓋:程序員大咖、源碼共讀、程序員共讀、數據結構與演算法、黑客技術和網路安全、大數據科技、編程前端、Java、Python、Web編程開發、Android、iOS開發、Linux、資料庫研發、幽默程序員等。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python開發 的精彩文章:

告訴你什麼叫憑本事單身!!!
看到沒有,這就是妹子沒男朋友的後果

TAG:Python開發 |