1. 程式人生 > 其它 >4.re包學習(正則表示式)

4.re包學習(正則表示式)

技術標籤:爬蟲新寵

正則表示式:字串模式(判斷字串是否符合一定的標準)


使用規則

可以建立一個模式物件以達到重複使用模式的目的,也可以直接呼叫search方法搜尋匹配

建立模式物件
1.建立模式物件
    # 建立一個模式物件,匹配所有連續的大寫字母
    pat = re.compile("[A-Z]*")
    # 匹配所有小寫字元'a'
    pat2 = re.compile("a")
2.執行查詢或替換
    m = pat.search("ABC12s4Da433D5FGA53a")
    print(m)

search:左閉右開區間,並且結果是從前往後首次匹配

    m = pat.findall("ABC12s4Da433D5FGA53a")
    print(m)

findall:查詢所有匹配的字串,結果集為列表

    m = pat2.sub("A", "abcdcasd")
    print(m)

模式物件.sub(),從sub第二個引數中找出所有能匹配模式物件規則的內容全部替換成第一個引數的內容


不建立模式物件
    # 查詢
    m = re.search("asd", "AasdF")  # 引數(匹配規則,要匹配的字串)pattern,string
    print(m)

re.search(“asd”, “AasdF”)是:<re.Match object; span=(1, 4), match=‘asd’>

    # 查詢
    print(re.findall("[A-Z]+", "AsDaDFGAa"))  # 一個到多個字元組合

re.findall("[A-Z]+", “AsDaDFGAa”)是:[‘A’, ‘D’, ‘DFGA’]

    # sub替換
    print(re.sub("a", "A", "abcdcasd"))  # 在"abcdcasd"中找到a並用A替換

re.sub(“a”, “A”, “abcdcasd”)是:AbcdcAsd

注意事項:
a = "\aadb-\'"
a = r"\aadb-\'"  # 不加r,\a會被當成一個字元

以上兩條語句輸出結果分別是:在這裡插入圖片描述

建議在正則表示式中,被比較的字串前加r,就可以不用擔心轉移字元的問題


正則表示式相關細則

正則表示式的常用操作符

操作符說明例項
.表示任何單個字元
[]字符集,對單個字元給出取值範圍[abc]表示a、b、c , [a-z]表示a到z單個字元
[^ ]非字符集,對單個字元給出排除範圍[^abc]表示非a或b或c的單個字元
*前一個字元0次或無限次擴充套件abc * 表示 ab、abc、abcc、abccc等
+前一個字元1次或無限次擴充套件abc+ 表示 abc、abcc、abccc等
?前一個字元0次或1次擴充套件abc?表示 ab、abc
|左右表示式任意一個abc|def 表示 abc、 def
{m}擴充套件前一個字元m次ab{2}c表示abbc
{m,n}擴充套件前一個字元m~n次(含n)ab{l,2}c表示abc、abbc
^匹配字串開頭^abc表示abc且在一個字串的開頭
$匹配字串結尾abc$表示abc且在一個字串的結尾
( )分組標記,內部只能用|操作符(abc)表示abc,(abc
\d數字,等價於[0-9]
\w單詞字元,等價於[A-Za-z0-9_]國外的一些網站要求使用者名稱是字母數字下劃線

這裡推薦部落格園的:史上最全常用正則表示式大全


Re庫的主要函式功能

函式說明
re.search()在一個字串中搜索匹配正則表示式的第一個位置,返回match物件
re.match()從一個字串的開始位置起匹配正則表示式,返回match物件
re.findall()搜尋字串,以列表型別返回全部能匹配的子串
re.split()將一個字串按照正則表示式匹配結果進行分割,返回列表型別
re.finditer()搜尋字串,返回一個匹配結果的迭代型別,每個迭代元素是match物件
re.sub()在一個字串中替換所有匹配正則表示式的子串,返回替換後的字串

藍色部分函式需要重點學會使用


可選標誌修飾符

正則表示式可以包含一些可選標誌修飾符來控制匹配的模式。修飾符被指定為可選的標誌。多個標誌 可以誦過按位OR(|)它們來指定。如re.l | re.M被設定成l和M標誌

修飾符描述
re.l使匹配對大小寫不敏感
re.L做本地化識別(locale-aware)匹配
re.M多行匹配,影響^和$
re.S使.匹配包含換行在內的所有字元
re.U根據Unicode字符集解析字元。這個標誌影響\w, \W, \b, \B.
re.X該標誌通過給予更靈活的格式以便將正則表示式寫得更易於理解。

任務驅動型開發:對豆瓣Top250電影爬取的資料進行解析

解析得到:***電影詳情連結 圖片連結 影片中文名 影片外文名 評分 評價數 概述 相關資訊***這些內容

import re  # 正則表示式,進行文字匹配
# import bs4 #只需要使用bs4中的BeautifulSoup因此可以如下寫法:
from bs4 import BeautifulSoup  # 網頁解析,獲取資料
import xlwt  # 進行excel操作
import sqlite3  # 進行SQLlite資料庫操作
import urllib.request, urllib.error  # 指定url,獲取網頁資料


def main():
    # 爬取的網頁
    baseurl = "https://movie.douban.com/top250?start="
    # # 儲存的路徑
    savepath = ".\\豆瓣電影Top250.xls"  # 使用\\表示層級目錄或者在整個字串前加r“.\豆瓣電影Top250”
    savepath2Db = "movies.db"
    # # 1.爬取網頁
    # print(askURL(baseurl))
    datalist = getData(baseurl)
    print(datalist)



# 影片詳情連結的規則
findLink = re.compile('<a href="(.*?)">')  # 建立正則表示式物件
# 影片圖片的連結規則
findImgSrc = re.compile('<img alt=".*src="(.*?)"', re.S)  # re.S忽略換行
# 影片片名
findTitle = re.compile('<span class="title">(.*)</span>')
# 影片評分
findRating = re.compile('<span class="rating_num" property="v:average">(.*)</span>')
# 評價人數
# findJudge = re.compile('<span>(\d*)(.*)人評價</span>')
findJudge = re.compile('<span>(\d*)人評價</span>')
# 概況
findInq = re.compile('<span class="inq">(.*)</span>')
# 影片相關內容
findBd = re.compile('<p class="">(.*?)</p>', re.S)  # 中間有</br>,因此要忽略換行符


# 爬取網頁
def getData(baseurl):
    datalist = []
    for i in range(0, 10):  # 一頁25條電影
        url = baseurl + str(i*25)
        html = askURL(url)  # 儲存獲取到的網頁原始碼
        # print(html)
        # 2.解析資料(逐一)
        soup = BeautifulSoup(html, "html.parser")  # 使用html.parser解析器解析html文件形成樹形結構資料
        for item in soup.find_all("div", class_="item"):  # 查詢符合要求的字串,形成列表
            # print(item)
            data = []  # 儲存一部電影的資訊
            item = str(item)
            # 影片詳情連結
            link = re.findall(findLink, item)[0]
            data.append(link)
            # 圖片
            img = re.findall(findImgSrc, item)[0]
            data.append(img)
            # 標題
            titles = re.findall(findTitle, item)
            if(len(titles) == 2):
                ctitle = titles[0]  # 中文名
                data.append(ctitle)
                otitle = titles[1].replace("/", "")
                data.append(otitle)  # 外文名
            else:
                data.append(titles[0])
                data.append(' ')  # 外文名留空
            # data.append(title)
            # 評分
            rating = re.findall(findRating, item)[0]
            data.append(rating)
            # 評價人數
            judgeNum = re.findall(findJudge, item)[0]
            # print(judgeNum)
            data.append(judgeNum)
            # 新增概述
            inq = re.findall(findInq, item)
            if len(inq) == 0:
                data.append(" ")
            else:
                data.append(inq[0].replace("。", ""))
            # 影片相關內容
            bd = re.findall(findBd, item)[0]
            bd = re.sub('<br(\s+)?/>(\s+)?', " ", bd)  # 去掉</br>
            bd = re.sub('/', " ", bd)  # 替換/
            data.append(bd.strip())  # 去掉前後的空格

            datalist.append(data)  # 把處理好的一部電影的資訊儲存
        # for it in datalist:
        #     print(it)
    return datalist


# 得到執行url的網頁資訊
def askURL(url):
    # 頭部資訊 其中使用者代理用於偽裝瀏覽器訪問網頁
    head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                          "Chrome/87.0.4280.88 Safari/537.36"}
    req = urllib.request.Request(url, headers=head)
    html = ""  # 獲取到的網頁原始碼
    try:
        response = urllib.request.urlopen(req)
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        if hasattr(e, "code"):  # has attribute
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
    return html


if __name__ == '__main__':
    main()

對解析的資料進行append時,需要注意有些值本身就是空值,比如說電影外名以及電影概述,儲存前需要判斷,如果時空值,需要以空字串或者給定一個空格儲存,否則會對後面插入表格或者資料庫造成影響