日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

Python爬虫自学之第(④)篇——强大的正则表达式,re模块

發(fā)布時間:2023/12/10 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python爬虫自学之第(④)篇——强大的正则表达式,re模块 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題外話:

《Pi Network 免費(fèi)挖礦國外熱門項目 一個π幣大約值3元到10元》相信過去BTC的人,信不信未來的PI,了解一下,唯一一個高度與之持平的項目

?

如果把BeautifulSopu比喻成通過線索一步步接近目標(biāo)的偵探的話,那么正則表達(dá)式就是牛逼哄哄的“天眼系統(tǒng)”,只要提供一些目標(biāo)的特征,無論搜索范圍多大,只要存在那么一兩個符合特征的目標(biāo),全都會被它直接逮住。

?

特性

牛逼王

  • BS的爸爸,我告訴你個秘密,其實(shí)BeautifulSoup也是用正則實(shí)現(xiàn)的,而且它find_all的參數(shù)里還能接收正則呢
  • 信息精確定位,BeautifulSoup用的是節(jié)點(diǎn)定位,可能會出現(xiàn)多個符合條件的節(jié)點(diǎn)(卻沒有目標(biāo)信息);正則是直接針對目標(biāo)信息,以字符為單位匹配,一次篩選出正確結(jié)果(前提是寫好正則)
  • 能獲取信息的部分,有時候完整的信息不是你想要的,你只想取它的某一部分,正則能搞定,BS只能先獲取完整信息再分離。
  • 用途大著呢,不要以為正則只能爬蟲,前后端都少不了正則,你填個信息判斷是否合法這都是正則,總之學(xué)到賺到

勸退大王+

這么強(qiáng)大的方法是不是看到都心動了,不過強(qiáng)大是有代價的,較難上手很難精通這兩根大棒一下子錘走了不少初學(xué)者。當(dāng)時學(xué)的我是這樣的:

  • 抽象&可讀性差。為了逮住某個目標(biāo),你可能要寫一條長長的,看到自己都頭暈的正則表達(dá)式,看上去就像亂碼一樣。舉個栗子,如果你要匹配一個ip地址,正則表達(dá)式會是這樣

    匹配ip地址:((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d)) ——真·亂碼
  • 編寫時出錯率高,新手很難一次寫對,需要不停地修改幾次十幾次才能pass(大腦在顫抖)
  • 難于優(yōu)化,優(yōu)化好的正則能提高匹配速度,然而你這新手還想優(yōu)化,能匹配對就很不錯了(正則暗中偷笑)

如果有足夠的自信和毅力不被正則擊倒,那就來吧。(屁,學(xué)正則還不是遲早的事!)

re 模塊

python 自帶模塊,直接導(dǎo)入即可。有匹配,替換等方法。
思考了許久后筆者覺得還是先講表達(dá)式(規(guī)則)好,因?yàn)槟承┓椒ǖ睦斫馐且私獗磉_(dá)式的。
下文的規(guī)則是完全版的,花了很久寫成,分享給讀者,順便當(dāng)成自己的網(wǎng)上筆記。

如果你學(xué)正則只是單單用來爬蟲的話,你只要熟悉“字符匹配”,“分組&或&轉(zhuǎn)義”,“預(yù)定字符集”,“數(shù)量詞”,“非貪婪模式”和(?:)取消分組,了解(或干脆不學(xué))“邊界匹配”,“特殊構(gòu)造”就行了。

如果你覺得正則是你未來工作的剛需的話,推薦熟悉所有規(guī)則。

匹配規(guī)則(pattern)

規(guī)則其實(shí)是一個原字符串如r'表達(dá)式'/r"表達(dá)式",較正式的叫法是模式字符串。最后再說一句,匹配以單個字符為單位(除括號能把多個字符打包成分組(整體)來匹配


表達(dá)式本質(zhì)是字符串,不要單引(雙引)號里套單引(雙引)號,會出錯。

字符匹配

  • 任一字符(空格也算)——就是匹配這個字符,某些字符因?yàn)樵谡齽t中有特殊用途需前加反斜杠轉(zhuǎn)義如 [ { . | ( ) ^ * + ? $
  • .——英文句號,匹配除換行符\n外的任意單個字符
  • []——匹配中括號里的任一字符,與-結(jié)合還能表示范圍內(nèi)的任一字符,中括號內(nèi)的字符除\外會自動轉(zhuǎn)義,還有小心多個中括號嵌套錯誤
  • [^]——中括號最前面加^,與[ ]反義,匹配一個不在中括號里的字符,也可以用橫杠-
r'[abcd]'#匹配一個a或b或c或d r'[0-9]'#匹配一個0至9的數(shù),-的作用域是左右各一個字符 r'[a-z]' r'[A-Z]'#分別匹配a到z或A到Z的一個字母 r'[12-89]'#注意因?yàn)槭菃巫址ヅ?匹配的是1,2到8的數(shù),9(即1到9的一個數(shù)),不是12到89的數(shù) r'[{.|()^*+?$\\]'#匹配 { . | ( ) ^ * + ? $ \中任一個,\要轉(zhuǎn)義 r'[^a-zA-Z]'#匹配一個不是字母的字符

分組&或&轉(zhuǎn)義

  • ()——括號,表達(dá)式分組(第n組,n=1,2,3....99,從左往右數(shù)),并形成子表達(dá)式
  • (?P<name>)——擁有括號的功能,但能為該分組再指定一個自定名字
  • (?P=name)——引用分配過名字的分組,但沒有分組功能
  • |——或,左右規(guī)則任意匹配一個,從左往右嘗試匹配,一旦成功就跳過后面的規(guī)則。|沒被包在括號中間的話它的作用域是整個表達(dá)式,被包的話作用域在括號內(nèi)
  • \——反斜杠,后接功能字有符轉(zhuǎn)義功能,后接數(shù)字(1到99)有引用分組的功能,后接某些字母又有特殊功能
r'abc|def|ghi'#匹配abc或def或ghi r'ma(?:k|d)e'#匹配make或made r'(abc)def\1'#相當(dāng)于r'(abc)defabc',匹配abcdefabc r'(?P<ok>abc)f(?P=ok)'#為(abc)子組分配了“ok”的名字,然后再引用,匹配abcfabc

預(yù)定字符集

  • \d——匹配任一個數(shù)字(0~9)
  • \D——匹配一個非數(shù)字字符,與\d互補(bǔ)
  • \s——匹配一個空白字符,包括空格,\t,\n,\r,\n,\f,\v
  • \S——匹配一個非空白字符
  • \w——匹配一個單詞字符。unicode下匹配各種語言的單個字符,單個數(shù)字,和下橫線。ASCII下匹配單個英文字母,單個數(shù)字,和下橫線
  • \W——匹配一個非單詞字符
r'\w' #能匹配'物語&ものがたり'中的:物,語,も,の,が,た,り,漢語日語的單字,其他語言同理

數(shù)量詞(接在字符或子組后)

  • {n}——作用于前一個字符或子表達(dá)式,匹配它重復(fù)n次
  • {min,max}——作用于前一個字符或子表達(dá)式,匹配它重復(fù)重復(fù)多少次min~max次,min和max可只寫一個設(shè)置重復(fù)下限或上限,但逗號不能省,不寫min時min默認(rèn)為0
  • *——星號,作用于前一個字符或子表達(dá)式,匹配它零次或多次
  • +——作用于前一個字符或子表達(dá)式,匹配它至少一次
  • ?——作用于前一個字符或子表達(dá)式,匹配它零次或一次
r'z{3}'#匹配zzz r'z{0,3}'#匹配z或zz或zzz r'(?:abc){2}'#對子表達(dá)式匹配兩次,匹配abcabc,(?:)是一個用法,不分組的意思,詳看后面 #星號加號問號同理

非貪婪模式

  • 在數(shù)量詞后接?,對前面的數(shù)量詞開啟非貪婪模式,意思就是在能匹配的前提下盡可能少的重復(fù)匹配
  • 正則默認(rèn)開啟貪婪模式
r'<.+>'#默認(rèn)貪婪,對于'<abc><def>'能匹配到'<abc><def>'整條,因?yàn)?貪婪地把尖括號也匹配掉了 r'<.+?>'#非貪婪,對于'<abc><def>'能匹配到'<abc>'和'<def>'

邊界匹配

  • ^——放在表達(dá)式的最前面,作用域是表達(dá)式,在多行模式中,在每一行匹配字符串開頭(多行模式要手動開啟,否則和\A沒什么區(qū)別)
  • $——放在表達(dá)式的最后面,作用域是表達(dá)式,在多行模式中,在每一行匹配字符串末尾(多行模式要手動開啟,否則和\Z沒什么區(qū)別)
  • \A——放在表達(dá)式的最前面,作用域是表達(dá)式,匹配字符串開頭,不能多行匹配
  • \Z——放在表達(dá)式的最后面,作用域是表達(dá)式,匹配字符串末尾,不能多行匹配
  • \b——不匹配字符,只匹配一個邊界,匹配\w和\W或\W和\w的邊界(單詞字符和非單詞字符的邊界)
  • \B——不匹配字符,只匹配一個邊界,與\b相反,匹配\w和\w或\W和\W的邊界
r'^abc|^def'#匹配abc開頭或def開頭,開啟了多行模式時,對字符串'abcd\ndefh'能匹配出abc,def兩個 r'abc$|def$'#匹配abc結(jié)尾或def結(jié)尾,開啟了多行模式時,對字符串'0abc\n0def'能匹配出abc,def兩個 r'\Aabc'#匹配abc開頭,因?yàn)椴荒芏嘈衅ヅ?#xff0c;就算開啟多行模式,對字符串'abcd\nabcd'只能匹配到前面的abc #\Z同理 r'\w\b\W'#匹配“單詞字符+非單詞字符”的結(jié)構(gòu)如'a!','1%' #\B同理

特殊構(gòu)造(不作為分組,不被findall捕獲)

    • (?:)——取消括號的分組功能,使其不會被findall方法捕獲
    • (?#)——#后寫注釋內(nèi)容,整個(?#)會被忽略
    • A(?=)——A之后的字符串需要匹配括號里的表達(dá)式A才會被匹配,一定用在表達(dá)式的最后(A是表達(dá)式,(?=)內(nèi)的表達(dá)式不會被匹配捕捉,下同)
    • A(?!)——A之后的字符串需要不匹配括號里的表達(dá)式A才會被匹配,一定用在表達(dá)式的最后
    • (?<=)A——A之前的字符串需要匹配括號里的表達(dá)式A才會被匹配,一定用在表達(dá)式的最前,括號內(nèi)的表達(dá)式需固定長度不能使用除{n}外的數(shù)量詞
    • (?<!)A——A之前的字符串需要不匹配括號里的表達(dá)式A才會被匹配,一定用在表達(dá)式的最前,括號內(nèi)的表達(dá)式需固定長度不能使用除{n}外的數(shù)量詞
r'(ab(?=cde))'#匹配后面是bcd的ab r'a(?!\d+)'#匹配后面不跟一串?dāng)?shù)字的a,后括號可用所有數(shù)量詞 r'(?<=abc)de'#匹配前面是abc的de r'(?<!\d{3})a'#匹配前面不是三個數(shù)字的a,前括號可以用{n}但是不能用不定量的數(shù)量詞
  • ?(?iLmsux)——放在表達(dá)式最前面,為所在的表達(dá)式設(shè)置模式,”i”, “L”, “m”, “s”, “u”, “x”,它們不匹配任何字串,對應(yīng)python中re模塊當(dāng)中的(re.I, re.L, re.M, re.S, re.U, re.X)的6種模式,下面flag參數(shù)講
r'(?i)abc'#“i”對應(yīng)re.I,忽略大小寫模式,能匹配Abc,ABC,abc等

方法&參數(shù)

相比于繁雜的規(guī)則,方法則要簡單多了,常用的就這幾個:

  • re.search(pattern,string,flags=0),返回第一個匹配的match對象(內(nèi)含匹配字符串的信息)
  • re.findall(pattern,string,flags=0),返回所有匹配分組的字符串組成的列表,沒設(shè)置分組相當(dāng)于整個表達(dá)式就是一個分組
  • #如果表達(dá)式有多個分組,會返回復(fù)雜的列表,因此findall中的表達(dá)式通常只有一個分組
  • re.finditer(pattern,string,flags=0),同findall功能,但是返回的是迭代器

#分組為(abc),findall只捕捉被數(shù)字包起來的abc返回列表['abc','abc'] re.findall(r'\d+(abc)\d+','1abc1,2abc2') #整個表達(dá)式匹配abab加一個兩位數(shù),(?:)取消了ab的分組,findall只捕捉abab加一個數(shù),返回列表['abab1','abab2'] re.findall(r'((?:ab){2}\d)\d','abab11,abab22')
  • pattern = re.compile(pattern,flags=0),把規(guī)則打包返回(如多次使用該規(guī)則),相當(dāng)與pattern和flag的合體,當(dāng)成pattern使用可免去設(shè)置flags
  • re.sub(pattern,repl,string,count=0,flags)把匹配到的部分用指定字符串repl替換,count設(shè)置替換次數(shù),默認(rèn)為零替換所有

參數(shù):

  • pattern:接收模式字符串,即表達(dá)式,也可以接收打包的規(guī)則
  • string:接收待匹配字符串,如html文檔
  • flags:模式(標(biāo)簽),接受以下模式,多個模式用“|”分開如 flags=re.I|re.M

    • re.I = re.IGNORECASE ? 忽略大小寫
    • re.L = re.LOCALE ? 支持當(dāng)前語言,為了支持多語言版本的字符集使用環(huán)境
    • re.U = re.UNICODE ? 使用w,W,b,B這些元字符時將按照UNICODE定義的屬性
    • re.M = re.MULTILINE ? 開啟多行模式
    • re.S = re.DOTALL ? 使.能匹配換行符\n
    • re.X = re.VERBOSE ? 可以忽略正則表達(dá)式中的空白和#號的注釋,不匹配空格和#注釋
    • re.A ?開啟ASCII模式

match對象方法

列出常用方法,下面的match是對象

  • match.group(id/name)id是分組序號(1~99),name是分組的自定名字,返回指定分組的字符串;不傳參數(shù)數(shù)是返回整條匹配字符串
  • match.start(id/name),match.end(id/name),match.span(id/name),分別返回指定分組字符串在整個字符串中的開始位置,結(jié)束位置,范圍。


正則慢慢學(xué)就行,正則的使用后面會有實(shí)例讓大家熟悉

總結(jié)

以上是生活随笔為你收集整理的Python爬虫自学之第(④)篇——强大的正则表达式,re模块的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。