Day25--Python--re,模塊(regular expression)

一 . re
1. import re
findall() 查找全部結果
finditer() 查找到的結果返回迭代器
search() 查找. 若是查找到第一個結果,就中止. 若是查找不到結果,返回None
match() 從頭開始找,找到第一個就中止
import re

# findall()
lst = re.findall('a', 'adfssafdseaa')
print(lst)

# finditer()
it = re.finditer('\d+', '這個月28號又發了10000元')  # 28    10000
print(it)  # <callable_iterator object at 0x000001B488083940> 迭代器
for el in it:   # 從迭代器中獲取到的el是分組的信息
    print(el.group())   # 獲取具體信息

# search()
ret = re.search('z', 'adfasfgfewa') # 若是查找不到返回None,則沒法調用group,會報錯
print(ret.group())

# match()
ret = re.match('a', 'dasffgsafads')  # 開頭不是a,返回None, ret=None,沒法調用group,會報錯
print(ret.group())
View Code 示例

 

    2. 操做
1. split 切割.按照正則切割
2. sub 替換 subn 替換並顯示替換次數
import re
lst = re.split(r'a', 'afssgsdaafgew')  # 切a
print(lst)

lst1 = re.split(r'[ab]', 'abadffdsabgsagewr') # 切a或b
print(lst1)

line = 'abc aa;bb,cc | dd(xx).xxx 12.12\'  xxxx'

# 按空格切
print(re.split(r' ', line))
print(re.split(r'[ ]', line))
# 按空白切
print(re.split(r'\s', line))
print(re.split(r'[\s]', line))
# 多字符匹配
print(re.split(r'[;,]', line))
# 使用括號捕獲分組的時候,默認保留分割符
print(re.split(r'([;])', line))
# 去掉;
print(re.split(r'(?:;)', line))
print(re.split(r';', line))
View Code split示例
import re
# sub 替換
ret = re.sub('250', '__sb__', 'alex250taibai250wusir250dd')
print(ret)
# 顯示替換了多少次
ret1 = re.subn('250', '__sb__', 'alex250taibai250wusir250dd')
print(ret1)
View Code sub和subn示例

     

  爬蟲重點: 用compile編譯正則表達式html

# 爬蟲重點
# eval, exec, compile 內置函數回顧
import re
# c = compile('code', 'filename', 'mode')  # 代碼, 文件名, 模式(eval執行並返回結果, exec執行,不返回結果, single當存放的代碼有交互時使用)
li = re.findall(r'\d+', '小明昨天賺了5000塊, 小紅賺了1000塊')
print(li)

obj = re.compile(r'\d+')  # 編譯正則表達式, 當正則表達式過於複雜很長的時候,能夠直接使用,不須要複製到代碼中
lst = obj.findall('小明昨天賺了5000塊, 小紅賺了1000塊')
print(lst)
View Code

    (?P<名字> 正則) 把正則匹配到的內容分組成"名字"組python

import re
obj = re.compile(r'(?P<id>\d+)(?P<name>e+)') # 從正則表達式匹配的內容每一個組起名 字 ret = obj.search('abc123eeee') # 搜索 print(ret.group()) # 結果: 123eeee print(ret.group("id")) # 結果: 123 # 獲取id組的內容 print(ret.group("name")) # 結果: eeee # 獲取name組的內容

 

    正則:在python中()表示分組  (?:)去掉python的分組  ()在split中表示保留刀正則表達式

 

import re
ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(ret) # ['oldboy'] 這是由於findall會優先把匹配結果組⾥內容返回,若是想要匹
配結果,取消權限便可
ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(ret) # ['www.oldboy.com']

 

import re
ret=re.split("\d+","eva3egon4yuan")
print(ret) #結果 : ['eva', 'egon', 'yuan']
ret=re.split("(\d+)","eva3egon4yuan")
print(ret) #結果 : ['eva', '3', 'egon', '4', 'yuan']
#在匹配部分加上()以後所切出的結果是不一樣的,
#沒有()的沒有保留所匹配的項,可是有()的卻可以保留了匹配的項,
#這個在某些須要保留匹配部分的使⽤過程是⾮常重要的。

 

利用優先級問題解決問題,爬取信息json

re.S 能忽略掉.不能匹配\n的問題  取值關鍵dom

用charset查看編碼模式      charset=gb2312  # 編碼模式 gbk  ide

import re
from urllib.request import urlopen
import ssl
# ⼲掉數字簽名證書
ssl._create_default_https_context = ssl._create_unverified_context
def getPage(url):
    response = urlopen(url)     # 和網頁連接
    return response.read().decode('utf-8')  # 返回正常的頁面源代碼, 一大堆HTML
def parsePage(s):   # s是頁面源代碼
    ret = re.findall('<div class="item">.*?<div class="pic">.*?<em .*?>(?P<id>\d+).*?'+
'<span class="title">(?P<title>.*?)</span>'+'.*?<span class="rating_num" .*?>(?P<rating_num>.*?)</span>.*?<span>'+
'(?P<comment_num>.*?)評價</span>', s, re.S)   # re.S 能忽略掉.不能匹配\n的問題 return ret
def main(num):
    url = 'https://movie.douban.com/top250?start=%s&filter=' % num
    response_html = getPage(url)    # 頁面源代碼
    ret = parsePage(response_html)
    print(ret)
    count = 0
    for i in range(10): # 10⻚
        main(count)
        count += 25

main(1)

 

import re
from urllib.request import urlopen

def getContent(url):
    return urlopen(url).read().decode("gbk")
# # 爬取 http://www.dytt8.net/ 上的內容
url = "http://www.dytt8.net"
content = getContent(url)
# 準備正則
obj = re.compile(r"\[<a .*?>最新電影下載</a>\]<a href='(?P<second_url>.*?)'>.*?</a>", re.S)
second_obj = re.compile(r'<div id="Zoom">.*?譯  名(?P<yiming>.*?)<br />◎片  名(?P<pianming>.*?)<br />.*?◎導  演(?P<daoyan>.*?)<br />◎主  演(?P<zhuyan>.*?)<br /><br />◎簡  介.*?<td .*?><a href="(?P<download>.*?)">', re.S)

it = obj.finditer(content)
for el in it:
    second_url = el.group("second_url")
    second_content = getContent(url+second_url)
    second_it = second_obj.finditer(second_content) # 拿到第二層經過正則匹配到的內容.
    print("************************************************************************")
    for second_info in second_it:
        print(re.sub("[\u3000]", "", second_info.group("yiming")))
        print(re.sub("[\u3000]", "", second_info.group("pianming")))
        print(re.sub("[\u3000]", "", second_info.group("daoyan")))
        print(re.split("<br />", re.sub("[\u3000]", "", second_info.group("zhuyan"))))
        print(re.sub("[\u3000]", "", second_info.group("download")))


'''
content = urlopen("http://www.dytt8.net").read().decode('gbk')
由於用到屢次,因此寫成函數以便調用
def getContent(url):
    return urlopen(url).read().decode('gbk')

'''
View Code爬取電影信息

 

import re
from urllib.request import urlopen

def getContent(url):   # 提取出功能方便屢次調用
    return urlopen(url).read().decode('gbk')  # 獲取源碼

url = "http://www.dytt8.net"
content = getContent(url)  # 獲取源碼
# print(content)  # 可查看源碼

# 準備正則
regular1 = re.compile(r"最新電影下載</a>]<a href='(?P<info_url>.*?)'>.*?</a><br/>", re.S)
regular2 = re.compile(r'◎譯  名 (?P<trans_name>.*?)<br />◎片  名 (?P<name>.*?)<br />.*?◎豆瓣評分 (?P<grade>.*?)/10'+
' from (?P<grade_num>.*?) users <br />.*?◎導  演 (?P<director>.*?) <br />◎主  演 (?P<actors>.*?) <br /><br />◎簡  介'+
'.*?bgcolor="#fdfddf"><a href="(?P<download_url>.*?)">', re.S)

name_url_iter = re.finditer(regular1, content)
for el in name_url_iter:
    info_url = el.group('info_url')
    content2 = getContent(url + info_url)
    info_iter = regular2.finditer(content2)
    for el2 in info_iter:
        print('*****************************************************************************')
        print('譯名:', el2.group('trans_name'))
        print('片名:', el2.group('name'))
        print('豆瓣評分:', el2.group('grade'))
        print('評分數量:', el2.group('grade_num'))
        print('導演:', el2.group('director'))
        print('主演:', re.split(r' <br />      ', el2.group('actors').replace('&middot;', '·')))
        print('下載地址:', el2.group('download_url'))
View Code 個人版本

 

import re, json
from urllib.request import urlopen

def getContent(url):   # 提取出功能方便屢次調用
    # print(url)
    return urlopen(url).read().decode('gbk')  # 獲取源碼



f = open('更多電影.txt', mode='a', encoding='utf-8')
# 準備正則
regular1 = re.compile(r'<b>.*?<a href="(?P<info_url>.*?)".*?', re.S)
regular2 = re.compile(r'◎譯  名 (?P<trans_name>.*?) <.*?名 (?P<name>.*?) <.*?代 (?P<date>.*?) <.*?評分 ' +
                      '(?P<grade>.*?)/.*?bgcolor="#fdfddf"><a href="(?P<download_url>.*?)">', re.S)

for i in range(4):
    url = "http://www.dytt8.net/html/gndy/dyzz/list_23_%s.html" % (i+1)
    content = getContent(url)  # 獲取源碼
    # print(content)  # 可查看源碼

    name_url_iter = re.finditer(regular1, content)
    for el in name_url_iter:
        info_url = el.group('info_url')
        content2 = getContent('http://www.dytt8.net' + info_url)
        info_iter = regular2.finditer(content2)
        for el2 in info_iter:
            # print('*****************************************************************************')
            print('譯名:', el2.group('trans_name'))
            print('片名:', el2.group('name'))
            print('豆瓣評分:', el2.group('grade'))
            print('上映日期:', el2.group('date'))
            print('下載地址:', el2.group('download_url'))
            dic = {}
            dic['譯名'] = el2.group('trans_name')
            dic['片名'] = el2.group('name')
            dic['豆瓣評分'] = el2.group('grade')
            dic['上映日期'] = el2.group('date')
            dic['下載地址:'] = el2.group('download_url')
            s = json.dumps(dic, ensure_ascii=False) + '\n'
            f.write(s)

f.close()
View Code 爬更多頁,寫入文件

 

二. 模塊

     模塊就是⼀個包含了python定義和明的⽂, 名就是模塊的名字加上.py. 換句話說咱們⽬前寫的全部的py均可以
     當作是⼀個模塊,可是咱們import的模塊⼀分紅四個通⽤類:
       1. 使⽤pyhton編寫的py
       2. 已被編譯共享庫或者DLLC或者C++擴展
       3. 包好⼀組模塊的包.
       4. 使⽤c編寫並接到python器的內模塊

import 模塊名
1. 檢查是否已經導入過 , 順序, 內存-> 內置 -> sys.path
2. 若是沒有導入過這個模塊. 先建立一個名稱空間
3. 而後把導入的模塊執行一遍. 把執行的結果放在剛纔的空間中
4. 當沒有as的時候是使用模塊的名字來引用這個名稱空間. 當有as的時候. 用as的名字命名空間
# 建立文件yitian.py
print("啊` 啊 啊啊 啊啊啊啊啊 啊!!!!")

main_person_man = "張無忌"
main_person_woman = "趙敏"

bad_person_one = "成昆"
bad_person_two = "周芷若"

def fight_on_light_top():

    print(main_person_man, "粉碎了",bad_person_one ,"的陰謀")

def fight_in_shaolin():
    print(main_person_man, "粉碎了", bad_person_two, "的陰謀")
View Code 建立文件yitian.py,文件名yitian即模塊名

 

import yitian as yt

print(yt.main_person_man)
yt.fight_in_shaolin() # 調⽤模塊中的函數
yt.fight_on_light_top()

print(globals())     # 能夠查看 當前空間中引入的內容

# # 模塊的加載順序: 從內存裏找. -> 內置 -> sys.path
# import sys
# print(sys.modules.keys()) # 查看到已經引入的模塊信息
# print(sys.path)
View Code 導入模塊,模塊名更改

      在Python中模塊是不可以重複入的. 當重複入模塊時. 系統會sys.modules斷該模塊是已經入了. 若是已經. 則不會重複
函數

import sys
print(sys.modules.keys()) # 查看導⼊的模塊.
import yitian # 導⼊模塊. 此時會默認執⾏該模塊中的代碼
import yitian # 該模塊已經導⼊過了. 不會重複執⾏代碼
import yitian
import yitian
import yitian
import yitian

 

        全部被導入的模塊都會放在sys.modules字典裏
     使用模塊中的內容. 模塊名字.方法/變量/類
from time import *   # 引入time模塊的全部對象. *表明全部對象: 變量,類,函數,引入後調用無需 模塊名. 直接使用便可time()  若是直接import time,則調用時須要time.time()
print(time())

print(sys.path)    # 查看路徑
print(sys.modules)     # 查看導入的模塊,是一個字典
print(sys.modules.keys())

 


    
     因爲模塊在入的時候會建其⾃⼰的名稱. 因此. 咱們在使⽤模塊中的量的時候⼀般是不會產⽣衝突.
import yitian
main_person_man = "胡⼀菲"
def fight_in_shaolin():
print(main_person_man, "⼤戰曾⼩賢")
print(yitian.main_person_man) # 張⽆忌
print(main_person_man) # 胡⼀菲
yitian.fight_in_shaolin() # 倚天屠⻰記中的
fight_in_shaolin() # ⾃⼰的

 

        __name__:
若是當前模塊是程序的入口. __name__的值:__main___
若是模塊是被其餘模塊引入的. __name__是模塊名
⾦庸:
import yitian
yitian.main_person_man = "滅絕師太"
⾦庸⼆號:
import yitian
import ⾦庸
print(yitian.main_person_man) # 滅絕師太.

⾦庸:
print(__name__)
# 此時若是運⾏該⽂件. __name____main__
⾦庸⼆號:
import ⾦庸
#此時打印的結果是"⾦庸"
(引入的模塊名,在哪一個引入模塊中調用__name__,則顯示哪一個模塊名)

      咱們能夠利⽤這個特性來控制模塊內些代碼是在被加的時候就⾏的. 些是在模
    塊被別⼈導入的時候就要⾏的. 也能夠屏蔽掉⼀些不但願別⼈導入就⾏的代碼. 尤爲是測
    試代碼.
編碼

if __name__ == '__main__':
        yitian.main_person_man = "滅絕師太" # 此時, 只有從該模塊做爲⼊⼝運⾏的時候才
會把main_person_man設置成滅絕師太
        print("哇哈哈哈哈哈") # 只有運⾏該模塊纔會打印. import的時候是不會執⾏這⾥的代
碼的    

    一次能夠引入多個模塊url

import time, random, json, yitian

 

 


from xxx import xxx
from 模塊 import 模塊中的內容
from 模塊 import * 不推薦

導入的內容能夠直接使用. 不須要模塊.xxx. 不要和當前模塊中的變量衝突
from yitian import main_person_man   #也能夠一行引入多個,也支持as更名字 
main_person_man = "滅絕" #  引入的名字和本身的變量是衝突的
print(main_person_man) # 先找 內存=>內置=>模塊  此處打印本身的變量

因此. 不要重名. 切記. 不要重名! 僅僅量名不要重複.咱們⾃⼰建立的py⽂件的名字不要和系統內置的模塊重名. . 入的模塊都是python的模塊. 切記, 切記.spa

若是確實須要用一樣的名字,能夠 my_模塊名.py  e.g. my_sys.py

相關文章
相關標籤/搜索