1. 程式人生 > >Python全棧(第一期)Day18

Python全棧(第一期)Day18

今日主要內容:
遞迴實戰複習
正則表示式
爬蟲小例子

一,遞迴複習

遞迴注意事項:
1,超過最大遞迴限制的報錯
2,只要寫遞迴函式,必須要有結束條件。
3,每一個條件之下都要有返回值
4,不要只看到return就認為已經返回了。要看返回操作是在遞迴到第幾層的時候發生的,然後返回給了誰。

1,斐波那契數求解

# 方法一
import time

def fib1(n):
    if n == 1 or n == 2:
        return 1
    return fib1(n-1) + fib1(n-2)


start = time.time()
ret = fib1(35)
end = time.time()
print(ret)
print(end - start)

print('000000000000000000000000000')



# 方法二
def fib2(n, l=[0]):
    l[0] += 1
    if n == 1 or n == 2:
        l[0] -= 1
        return 1, 1
    else:
        a, b = fib2(n-1)
        l[0] -= 1
        if l[0] == 0:
            return a+b
        return b, a+b
print(fib2(35))

print('000000000000000000000000000')


# 方法三
def fib3(n, a=1, b=1):
    if n == 1:
        return a
    return fib3(n-1, b, a+b)



start = time.time()
ret = fib3(35)
end = time.time()
print(ret)
print(end - start)

輸出結果:
9227465
2.2498440742492676
000000000000000000000000000
9227465
000000000000000000000000000
9227465
0.0
能夠很明顯看到第一種方法和第三種方法的耗時差異!

2,階乘

# 階乘
    #3! 3*2*1
    # 2! 2*1
    # 1! 1
def fac(n):
    if n == 1:
        return 1
    return n * fac(n-1)

print(fac(5))

輸出結果:
120

二,正則表示式

1,手機號碼匹配

# 方法一
while True:
    phone_number = input('please input your phone number : ')
    if len(phone_number) == 11 \
            and phone_number.isdigit()\
            and (phone_number.startswith('13') \
            or phone_number.startswith('14') \
            or phone_number.startswith('17') \
            or phone_number.startswith('18')):
        print('是合法的手機號碼')
        break
    else:
        print('不是合法的手機號碼')
        break

# 方法二
import re
phone_number = input('please input your phone number : ')
if re.match('^(13|14|15|17)[0-9]{9}$',phone_number):
        print('是合法的手機號碼')
else:
        print('不是合法的手機號碼')

輸出結果:
please input your phone number : 17824839335
是合法的手機號碼
please input your phone number : 17824839335
是合法的手機號碼

2,re模組下的常用方法

# re:一共用三個方法
# findall
# search
# match


ret = re.findall('[a-z]+', 'eva egon yuan')  #返回所有滿足匹配條件的結果,放在列表裡
print(ret)



ret = re.search('[a]', 'eva egon yuan')
print(ret)
if ret:
    print(ret.group())
# 從前往後,找到一個就返回,返回的變數需要呼叫group才能拿到結果
# 如果沒有找到,那麼返回None,呼叫group會報錯,但是我們如果用一個if語句,就一直都不會報錯。




ret = re.match('[a-z]+', 'eva egon yuan')
if ret:
    print(ret.group())
# match是從頭開始匹配,如果正則規則從頭開始可以匹配上,就返回一個變數。
# 匹配的內容需要用group才能顯示
# 如果沒匹配上,就返回None,呼叫group會報錯~

輸出結果:
[‘eva’, ‘egon’, ‘yuan’]
<_sre.SRE_Match object; span=(2, 3), match=‘a’>
a
eva

3.split

ret = re.split('[ab]', 'abcd')
# 先按'a'分割得到''和'bcd',在對''和'bcd'分別按'b'分割
print(ret)  # ['', '', 'cd']~

輸出結果:
[’’, ‘’, ‘cd’]

4,sub subn

ret = re.sub('\d', 'H', 'eva3egon4yuan4',2)
#將數字替換成'H',引數1表示只替換1個
print(ret)  #evaHegon4yuan4

ret = re.subn('\d', 'H', 'eva3egon4yuan4')
#將數字替換成'H',返回元組(替換的結果,替換了多少次)
print(ret)~

輸出結果:
evaHegonHyuan4
(‘evaHegonHyuanH’, 3)

5,compile

obj = re.compile('\d{3}')
#將正則表示式編譯成為一個 正則表示式物件,規則要匹配的是3個數字
ret = obj.search('abc123eeee') #正則表示式物件呼叫search,引數為待匹配的字串
print(ret.group())
ret = obj.search('abcashgjgsdghkash4536eeee3wr2') #正則表示式物件呼叫search,引數為待匹配的字串
print(ret.group())  ~

輸出結果:
123
453

6,finditer

import re
ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一個存放匹配結果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
# print(next(ret).group())  #檢視第一個結果
# print(next(ret).group())  #檢視第二個結果
# print([i.group() for i in ret])  #檢視剩餘的左右結果
for i in ret:
    print(i.group())~

輸出結果:
<callable_iterator object at 0x0000029D8B089710>
3
4
7
8
4

7,可以匹配分組內數值

import re
ret = re.search('^[1-9](\d{14})(\d{2}[0-9X])?$', '37142119981009002X')
print(ret.group())
print(ret.group(0))  # 可以匹配到分組內的數值
print(ret.group(1))
print(ret.group(2))~

輸出結果:
37142119981009002X
37142119981009002X
71421199810090
02X

8,分組

'''
?:
1,在量詞前面:匹配0/1次
2. 在量詞後邊:惰性匹配的標誌
3. 放在分組第一個:取消分組優先

'''

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']
~

輸出結果:
[‘oldboy’]
[‘www.oldboy.com’]

9,split

import re
ret = re.split("\d+", "eva3egon4yuan")
print(ret)  #結果 : ['eva', 'egon', 'yuan']

ret = re.split("(\d+)", "eva3egon4yuan") #有分組的時候,返回切割內容
print(ret) #結果 : ['eva', '3', 'egon', '4', 'yuan']~

輸出結果:
[‘eva’, ‘egon’, ‘yuan’]
[‘eva’, ‘3’, ‘egon’, ‘4’, ‘yuan’]

三,爬蟲的例子

import re
from urllib.request import urlopen

def getPage(url):
    response = urlopen(url)
    return response.read().decode('utf-8')


def parsePage(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)
    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




# url從網頁上把程式碼搞下來
# bytes decode ——> utf-8 網頁內容就是我的待匹配字串
# ret = re.findall(正則,帶匹配的字串)  #ret是所有匹配到的內容組成的列表
# 這只是一個簡單的網路爬蟲---->我們可以進一步轉化為文字


~