自學Python六 爬蟲基礎必不可少的正則


  要想做爬蟲,不可避免的要用到正則表達式,如果是簡單的字符串處理,類似於split,substring等等就足夠了,可是涉及到比較復雜的匹配,當然是正則的天下,不過正則好像好煩人的樣子,那么如何做呢,熟記正則元字符和語法,找個在線匹配測試網站隨時測試(其實在正則上我也是個菜逼。。。一直在慢(詢)慢(問)測(大)試(牛)中得到正解),不過要相信,用熟了自然就巧了!

  首先,推薦兩篇博客,分別介紹了python自帶的正則標准庫re以及regex模塊:Python正則表達式指南(re)     Python的regex模塊——更強大的正則表達式引擎。而我呢,最不擅長總結各種庫各種語法之類的了,本篇博客就稍微簡單介紹常用的以及爬蟲程序開發過程中的小例子!先說說比較常用的6個re中的函數:

  re.compile(pattern,flag)#根據正則匹配字符串以及附加條件,返回一個pattern對象

  re.search(pattern,string)#搜索整個字符串,知道發現符合正則表達式的字符串

  re.match(pattern,string)#從頭開始檢測字符串是否符合正則表達式,必須從字符串的第一個字符開始

  re.sub(pattern,replacement,string)#將字符串中根據正則匹配到的字符串用replacement替換

  re.split(pattern,string)#根據正則表達式分割字符串,將分割后的字符串放到list中返回

  re.findall(pattern,string)#根據正則表達式分割字符串,將找到的所有結果放到list中返回

  python中的匹配默認是貪婪的,所謂貪婪就是嘗試盡可能的匹配更多的字符,比如:正則表達式"ab*"如果用於查找字符串"abbbc",將找到"abbb",如果是非貪婪的呢,得到的結果就是"a"。同樣有時候我們時刻要注意轉義字符等等,在net中我們有@,在python中我們有r,用法一樣哦。讓我們先來看一段代碼:

1 >>> import re
2 >>>
3 >>> pattern = re.compile(r'hello',re.I)
4 >>> match = pattern.match('Hello World@!')
5 >>> if match:
6 ...     print match.group()
7 ...
8 Hello
9 >>>

  在上面的代碼中,我們先生成了一個pattern對象,然后進行了匹配,其中re.compile函數中,我們的re.I就是附帶條件:忽略大小寫。其他模式可以自行搜索之,各種模式之間可以互相配合。其實我們可以放棄用re.compile函數而直接這么寫:

1 >>> match = re.match('hello','hello world!')
2 >>> print match.group()
3 hello

  這樣做少了一行re.compile(pattern,flags)代碼,但是也少了pattern的對象,各位如何使用之就仁者見仁智者見智吧。

  python中還可以對正則匹配的返回結果進行進一步的控制,如:

1 >>> import re
2 >>> m = re.search("output_(\d{4})","output_2016.txt")
3 >>> print m.group()
4 output_2016
5 >>> print m.group(1)
6 2016
7 >>> print m.groups()
8 ('2016',)

  可以看到,我們的正則表達式output_(\d{4}) 其中包含一個正則表達式(\d{4}),像這樣被括號圈起來的正則表達式的一部分,我們稱之為群(group),我們可以用m.group(index)來查詢,group(0)是整個正則表達式的搜索結果,group(1)是第一個群,以此類推。。。。也許這樣看着並不方便,我們可以對群起名字:

>>> import re
>>> m = re.search("(?P<year>\d{4})\.(?P<mon>\d{2})\.(?P<day>\d{2})","output_2016.01.18.txt")
>>> m.groups()
('2016', '01', '18')
>>> m.groupdict()
{'year': '2016', 'mon': '01', 'day': '18'}
>>> m.group("year")
'2016'
>>> m.group("mon")
'01'
>>> m.group("day")
'18'

  讓我們看個實例:有一個文件,文件名為output_2016.01.18.txt。請讀取文件名中的日期時間信息,計算出當日是星期幾,並將文件名修改為output_yyyy-mm-dd-w.txt,其中w為星期幾。

1 import os,re,datetime
2 filename="output_1981.10.21.txt"
3 get_time=re.search("(?P<year>\d{4})\.(?P<month>\d{2})\.(?P<day>\d{2})\.",filename)
4 year=get_time.group("year")
5 month=get_time.group("month")
6 day=get_time.group("day")
7 date=datetime.date(int(year),int(month),int(day))
8 wd=date.weekday()+1
9 os.rename(filename,"output_"+year+"-"+month+"-"+day+"-"+str(wd)+".txt")

  好了,正則基礎就介紹到這里了,接下來讓我們試着進行一下爬蟲中的正則表達式。講個小例子:什么值得買的白菜價包郵信息。

  什么值得買——白菜價

  要爬取網頁信息,除了我們要得到網頁信息外最重要的就是把我們需要的信息提取出來,我們f12來看一下要提取的html代碼:

  我們看到我們想要得到的信息都在<h2 class="itemName">...</h2>之中。我們的正則表達式如下:

1 content = response.read().decode('utf-8')
2 pattern = re.compile('<h2 .*?itemName"><a.*?<span .*?black">(.*?)</span><span .*?red">(.*?)</span></a></h2>',re.S)
3 items = re.findall(pattern,content)
4 for item in items:
5     print item[0],item[1]

  .*?是一個固定搭配,.和*可以匹配任意多個字符,加上?就是最小匹配,也就是我們上面說的非貪婪模式。直白的說就是匹配盡可能短的字符串。

  (.*?)這個上面我們講了,他是正則匹配時的一個群。re.S標志在正則匹配的時候為點任意匹配模式,即點可以代表任意字符比如換行符。這樣我們就獲得了每個商品的名稱和價格。(整個爬蟲源碼在下一篇博客)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM