前言:
利用簡單的正規表示式,獲取響應內容爬取資料。
Part1 正規表示式(Regular Expression)
1.1 簡介
正規表示式,又稱規則表示式,它是一種文字模式,就是通過事先定義好的一些特定字元及這些特定字元的組合成一個規則,對文字字串進行匹配篩選過濾。
比如:“A1bc23ef45”這個字串,我只想要裡面的數字,通過正規表示式中的“\d”就可以快速的提取出來。
注:正規表示式線上測試工具:開源中國——實用工具——https://tool.oschina.net
1.2 常用字元
字元 | 描述 |
[...] | 匹配 [...] 中的所有字元,如[eno],將匹配Python is fun中的e n o字母(若有) |
[^...] | 匹配除了 [...] 中字元的所有字元,上面的例子取反 |
\w | 匹配字母、數字、下劃線。等價於 [A-Za-z0-9_] |
\s | 匹配任何空白字元,包括空格、製表符、換頁符等 |
\S | 匹配任何非空白字元 |
( ) | 標記一個子表示式的開始和結束位置。 |
* | 匹配前面的子表示式零次或多次。 |
. | 匹配除換行符 \n 之外的任何單字元。 |
? | 匹配前面的子表示式零次或一次,或指明一個非貪婪限定符 |
\ | 轉義字元 |
^ | 匹配輸入字串的開始位置 |
$ | 匹配輸入字串的結尾位置 |
+ | 匹配前面的子表示式一次或多次 |
\d | 匹配數字 |
\D | 匹配非數字 |
{n} | n 是一個非負整數,匹配確定的 n 次 |
{n,} | n 是一個非負整數,至少匹配n 次 |
{n,m} | m 和 n 均為非負整數,其中n <= m,最少匹配 n 次且最多匹配 m 次 |
.* | 貪婪匹配,匹配所有內容 |
.*? | 非貪婪匹配,在所有內容中匹配一次 |
1.3 re模組中的常用方法
1.3.1 findall 查詢字串中所有內容,返回符合條件的資料,返回的資料是列表形式
1 lst = re.findall('o','Python is fun otoy') 2 print(lst) 3 # 查詢字串中所有的o,返回三個['o', 'o', 'o']
1.3.2 search 返回匹配到的第一個結果,如果沒有返回None
lst = re.search('o','Python is fun otoy') print(lst) # <re.Match object; span=(4, 5), match='o'> lst = re.search('a','Python is fun otoy') print(lst) # None
1.3.3 match 只能從字串開頭進行匹配
1 lst = re.match('o','Python is fun otoy') 2 print(lst) 3 # None 4 5 lst = re.match('P','Python is fun otoyPPPP') 6 print(lst) 7 # <re.Match object; span=(0, 1), match='P'>
1.3.4 finditer 和findall差不多,但是返回值是一個迭代器
1 lst = re.finditer('o','Python is fun otoy') 2 print(lst) 3 # <callable_iterator object at 0x000002820BCF6B20> 4 5 # 獲取迭代器裡的內容 6 for i in lst: 7 print(i) 8 # <re.Match object; span=(4, 5), match='o'> 9 # <re.Match object; span=(14, 15), match='o'> 10 # <re.Match object; span=(16, 17), match='o'> 11 12 # 只想要o 13 for i in lst: 14 print(i.group())# o# o# o
注:從finditer中獲取內容,使用group方法,從search中獲取也是使用這個方法
Part2 思路
2.1 目標
地址:https://movie.douban.com/top250
訪問地址,F12開啟開發者工具檢視原始碼,可以看到需要資料都在前端頁面,開始分析需要的資料所在位置
2.2 步驟
發起請求——獲取響應文字——正規表示式解析獲取資料——資料儲存
Part3 編寫指令碼
3.1 匯入庫
1 import requests 2 import re 3 import csv
re模組和csv為python自帶,不需要安裝,這裡使用csv文字模式儲存資料,是因為csv儲存資料的特點:a,b,c 以逗號分割的格式,方便爬取資料後做進一步的處理分析。
3.2 擼程式碼
1 url = 'https://movie.douban.com/top250' 2 headers = { 3 "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0)Gecko/20100101 Firefox/85.0" 4 } 5 6 resp = requests.get(url=url, headers=headers).text 7 # 獲取到響應資料之後,轉換成text文字資料,這樣才能使用re來進行操作
3.3 分析
需要獲取到電影的連結,電影名字,年份/地區/分類,評分,評價人數
3.4 提前定義一個正規表示式,方便後面呼叫
1 obj = re.compile(r'<li>.*?<div class="item">.*?<a href="(?P<link>.*?)">.*?<span class="title">(?P<name>.*?)</span>.*?<br>(?P<year>.*?)</p>.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?<span>(?P<comments>.*?)</span>', re.S)
注:使用 .*? 匹配過濾掉中間的所有的內容,使用(.*?)將匹配到內容提取,(?P<name>.*?)將匹配到的內容賦值給"name"
3.5 獲取資料,寫入儲存
1 result = obj.finditer(resp) 2 fp = open('data.csv', 'w', encoding='utf-8') 3 wp = csv.writer(fp) 4 5 for it in result: 6 dic = it.groupdict() 7 dic['year'] = dic['year'].strip().replace(" ", "") 8 # 去除空格,替換字元 9 wp.writerow(dic.values()) 10 fp.close()
注:從響應的文字里匹配到資料,使用groupdict()方法,將資料放到字典裡,“year”匹配到的資料裡含有空格和特殊字元,使用strip()方法去除空格,然後使用replace()方法把特殊字元替換成空
Part4 完整程式碼
4.1 說明
按照上面的程式碼,爬取到的是第一頁的內容,只有25條資料,通過分析URL引數,改變引數內容發起請求即可獲取全部的資料。
1 import requests 2 import re 3 import csv 4 5 fp = open('data.csv', 'w', encoding='utf-8') 6 wp = csv.writer(fp) 7 8 for i in range(0, 256, 25): 9 url = f'https://movie.douban.com/top250?start={i}&filter=' 10 headers = { 11 "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0" 12 } 13 14 resp = requests.get(url=url, headers=headers).text 15 16 # 資料解析 17 obj = re.compile(r'<li>.*?<div class="item">.*?<a href="(?P<link>.*?)">.*?' 18 r'<span class="title">(?P<name>.*?)</span>.*?<br>(?P<year>.*?)</p>.*?' 19 r'<span class="rating_num" property="v:average">(?P<score>.*?)</span>.*?' 20 r'<span>(?P<comments>.*?)</span>', re.S) 21 22 result = obj.finditer(resp) 23 24 for it in result: 25 dic['year'] = dic['year'].strip().replace(" ", "") 26 # 去除空格,替換字元 27 wp.writerow(dic.values()) 28 29 fp.close() 30 print('top250已下載完成')
4.2 執行結果
奇盛測試攻城獅 專業就是不斷地學習,除去偶然性,你永遠無法發現認知以外的BUG。——C_N_Candy 公眾號