一 . 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())
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))
import re # sub 替換 ret = re.sub('250', '__sb__', 'alex250taibai250wusir250dd') print(ret) # 顯示替換了多少次 ret1 = re.subn('250', '__sb__', 'alex250taibai250wusir250dd') print(ret1)
爬蟲重點: 用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)
(?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') '''
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('·', '·'))) print('下載地址:', el2.group('download_url'))
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()
二. 模塊
模塊就是⼀個包含了python定義和聲明的⽂件, ⽂件名就是模塊的名字加上.py後綴. 換句話說咱們⽬前寫的全部的py⽂件均可以
當作是⼀個模塊,可是咱們import加載的模塊⼀共分紅四個通⽤類別:
1. 使⽤pyhton編寫的py⽂件
2. 已被編譯爲共享庫或者DLL或C或者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, "的陰謀")
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)
在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