使用了tkinter做了簡單頁面
首先分析要爬取的url, 發現每個頁面有25條內容, 總共有十頁, 第一頁的URL為https://movie.douban.com/top250?start=0&filter=
第二頁的url為https://movie.douban.com/top250?start=25&filter=
第三頁第四頁也是類似的URL, 只是修改了start後面的數字, 第一頁是0, 往後每增加25, 所以url的格式為https://movie.douban.com/top250?start=+{ID}
然後分析如何爬取內容:
首先爬取標題:
查看源代碼後, 發現標題是放在這樣的代碼:
12345
發現電影的名稱一般都放在
電影名稱1
這樣的標記對中, 所以根據這個可以寫出正則表達式:
(.*?)1
不過在後面的測試中發現這樣寫的話, 每個電影名稱能獲取兩個信息
肖申克的救贖 / The Shawshank Redemption12
顯然第二條信息不是我們想要的, 經過對比發現第二條信息中都會有兩個空格的代碼, 所以把&給過濾掉就可以了:
(.[^&]*?)1
接下來爬取評分, 評分一般放在這樣的代碼中:
716019人評價123456
這個正則就很好寫了:
"v:average">(.*?)1
這樣就ok啦, 這個程序還是非常簡單的, 上源代碼:
# -*- coding: utf-8 -*-from Tkinter import *from ScrolledText import ScrolledTextimport requests, re, threadingdef replite(ID): varl.set('正在獲取第%d頁內容' % (ID / 25 + 1)) html = 'https://movie.douban.com/top250?start=' + str(ID) response = requests.get(html).text # response = unicode(response, 'GBK').encode('UTF-8') response = response.encode('utf-8 ') # print response # reg = r'(.*?).*?"v:average">(.*?)' regTitle = r'(.[^&]*?)' regStars = r'.*?"v:average">(.*?)' regTitle = re.compile(regTitle) regStars = re.compile(regStars) titles = re.findall(regTitle, response) stars = re.findall(regStars, response) info = list(zip(titles, stars)) return infodef write(): varl.set('開始爬取內容') ID = 0 nums = 1 while ID < 250: res = replite(ID) ID += 25 for each in res: text.insert(END, 'No.%d\t%-30s%s分\n' % (nums, each[0], each[1])) nums += 1 varl.set('獲取內容成功')def start(): t1 = threading.Thread(target=write) t1.start()def save(): content = text.get("0.0", "end").encode('GBK') textfile = open(u'E:\\豆瓣電影排行250.txt', 'w') textfile.write(content) textfile.close()root = Tk()root.title('豆瓣電影top250')root.geometry('820x500+400+200')text = ScrolledText(root, font=('楷體', 15), width=80, height=20)text.grid()frame = Frame(root)frame.grid()# 啟動爬蟲功能startButton = Button(frame, text='開始', font=('楷體', 18), command=start)startButton.grid()startButton.pack(side=LEFT)# 保存爬取信息saveButton = Button(frame, text='保存文件', font=('楷體', 18), command=save)saveButton.grid()saveButton.pack(side=LEFT)# 退出程序exitButton = Button(frame, text='退出', font=('楷體', 18), command=frame.quit)exitButton.grid()exitButton.pack(side=LEFT)varl = StringVar()info_label = Label(root, fg='red', textvariable=varl)info_label.grid()varl.set('準備中....')root.mainloop()
下面給大家分享python正則詳解:
正則表達式是一個很強大的字符串處理工具,幾乎任何關於字符串的操作都可以使用正則表達式來完成,作為一個爬蟲工作者,每天和字符串打交道,正則表達式更是不可或缺的技能,正則表達式的在不同的語言中使用方式可能不一樣,不過只要學會了任意一門語言的正則表達式用法,其他語言中大部分也只是換了個函數的名稱而已,本質都是一樣的。下面,我來介紹一下python中的正則表達式是怎麼使用的。
首先,python中的正則表達式大致分為以下幾部分:
元字符
模式
函數
re 內置對象用法
分組用法
環視用法
所有關於正則表達式的操作都使用 python 標準庫中的 re 模塊。
一、元字符 (參見 python 模塊 re 文檔)
. 匹配任意字符(不包括換行符)
^ 匹配開始位置,多行模式下匹配每一行的開始
$ 匹配結束位置,多行模式下匹配每一行的結束
* 匹配前一個元字符0到多次
+ 匹配前一個元字符1到多次
? 匹配前一個元字符0到1次
{m,n} 匹配前一個元字符m到n次
\\ 轉義字符,跟在其後的字符將失去作為特殊元字符的含義,例如\\.只能匹配.,不能再匹配任意字符
[] 字符集,一個字符的集合,可匹配其中任意一個字符
| 邏輯表達式 或 ,比如 a|b 代表可匹配 a 或者 b
(...) 分組,默認為捕獲,即被分組的內容可以被單獨取出,默認每個分組有個索引,從 1 開始,按照"("的順序決定索引值
(?iLmsux) 分組中可以設置模式,iLmsux之中的每個字符代表一個模式,用法參見 模式 I
(?:...) 分組的不捕獲模式,計算索引時會跳過這個分組
(?P
...) 分組的命名模式,取此分組中的內容時可以使用索引也可以使用name (?P=name) 分組的引用模式,可在同一個正則表達式用引用前面命名過的正則
(?#...) 註釋,不影響正則表達式其它部分,用法參見 模式 I
(?=...) 順序肯定環視,表示所在位置右側能夠匹配括號內正則
(?!...) 順序否定環視,表示所在位置右側不能匹配括號內正則
(?<=...) 逆序肯定環視,表示所在位置左側能夠匹配括號內正則
(?
(?(id/name)yes|no) 若前面指定id或name的分區匹配成功則執行yes處的正則,否則執行no處的正則
\number 匹配和前面索引為number的分組捕獲到的內容一樣的字符串
\A 匹配字符串開始位置,忽略多行模式
-
\Z 匹配字符串結束位置,忽略多行模式
\b 匹配位於單詞開始或結束位置的空字符串
\B 匹配不位於單詞開始或結束位置的空字符串
\d 匹配一個數字, 相當於 [0-9]
\D 匹配非數字,相當於 [^0-9]
\s 匹配任意空白字符, 相當於 [ \t\n\r\f\v]
\S 匹配非空白字符,相當於 [^ \t\n\r\f\v]
\w 匹配數字、字母、下劃線中任意一個字符, 相當於 [a-zA-Z0-9_]
\W 匹配非數字、字母、下劃線中的任意字符,相當於 [^a-zA-Z0-9_]
二、模式
I IGNORECASE, 忽略大小寫的匹配模式, 樣例如下
s = 'hello World!'regex = re.compile("hello world!", re.I)print regex.match(s).group()#output> 'Hello World!'#在正則表達式中指定模式以及註釋regex = re.compile("(?#註釋)(?i)hello world!")print regex.match(s).group()#output> 'Hello World!'
L LOCALE, 字符集本地化。這個功能是為了支持多語言版本的字符集使用環境的,比如在轉義符\w,在英文環境下,它代表[a-zA-Z0-9_],即所以英文字符和數字。如果在一個法語環境下使用,缺省設置下,不能匹配"é" 或 "ç"。加上這L選項和就可以匹配了。不過這個對於中文環境似乎沒有什麼用,它仍然不能匹配中文字符。
M MULTILINE,多行模式, 改變 ^ 和 $ 的行為
s = '''first linesecond linethird line'''# ^regex_start = re.compile("^\w+")print regex_start.findall(s)# output> ['first']regex_start_m = re.compile("^\w+", re.M)print regex_start_m.findall(s)# output> ['first', 'second', 'third']#$regex_end = re.compile("\w+$")print regex_end.findall(s)# output> ['line']regex_end_m = re.compile("\w+$", re.M)print regex_end_m.findall(s)# output> ['line', 'line', 'line']
S DOTALL,此模式下 '.' 的匹配不受限制,可匹配任何字符,包括換行符
s = '''first linesecond linethird line'''#regex = re.compile(".+")print regex.findall(s)# output> ['first line', 'second line', 'third line']# re.Sregex_dotall = re.compile(".+", re.S)print regex_dotall.findall(s)# output> ['first line\nsecond line\nthird line']
X VERBOSE,冗餘模式, 此模式忽略正則表達式中的空白和#號的註釋,例如寫一個匹配郵箱的正則表達式
email_regex = re.compile("[\w+\.]+@[a-zA-Z\d]+\.(com|cn)")email_regex = re.compile("""[\w+\.]+ # 匹配@符前的部分 @ # @符 [a-zA-Z\d]+ # 郵箱類別 \.(com|cn) # 郵箱後綴 """, re.X)
U UNICODE,使用 \w, \W, \b, \B 這些元字符時將按照 UNICODE 定義的屬性.
正則表達式的模式是可以同時使用多個的,在 python 裡面使用按位或運算符 | 同時添加多個模式
如 re.compile('', re.I|re.M|re.S)
每個模式在 re 模塊中其實就是不同的數字
print re.I# output> 2print re.L# output> 4print re.M# output> 8print re.S# output> 16print re.X# output> 64print re.U# output> 32
四、re 內置對象用法
SRE_Pattern 這個對象是一個編譯後的正則表達式,編譯後不僅能夠複用和提升效率,同時也能夠獲得一些其他的關於正則表達式的信息
屬性:
flags 編譯時指定的模式
groupindex 以正則表達式中有別名的組的別名為鍵、以該組對應的編號為值的字典,沒有別名的組不包含在內。
groups 正則表達式中分組的數量
pattern 編譯時用的正則表達式
s = 'Hello, Mr.Gumby : 2016/10/26'p = re.compile('''(?: # 構造一個不捕獲分組 用於使用 | (?P
\w+\.\w+) # 匹配 Mr.Gumby | # 或 (?P \s+\.\w+) # 一個匹配不到的命名分組 ) .*? # 匹配 : (\d+) # 匹配 2016 ''', re.X)
好了,今天的知識就分享到這裡,歡迎關注愛編程的南風,私信關鍵詞:學習資料,獲取更多學習資源,如果文章對你有有幫助,請收藏關注,在今後與你分享更多學習python的文章。同時歡迎在下面評論區留言如何學習python。
閱讀更多 愛編程的南風 的文章