網址:豆瓣電影 Top 250
requests (用于發送HTTP請求) | re (用于字符串匹配和操作) |
確定需要爬取的數據 :
- 電影的名稱
- 電影的年份
- 電影的評分
- 電影評論人數
一. 發送請求 模擬瀏覽器向服務器發送請求
準備工作 -分析頁面:
F12 or 右擊點擊檢查 查看頁面源代碼 目的是確定數據是否為靜態數據
Ctrl + F 快捷鍵打開搜索框 將我們所需要爬取的數據輸入
發現數據都在前端的頁面當中 即拿到頁面的源代碼 從中提取數據
接著復制瀏覽器的URL地址 在pycharm里面構建請求
# 導包
import requests
import reurl = 'https://movie.douban.com/top250'# 構建請求體
# user-agent 即UA 為瀏覽器的基本信息 爬蟲程序就是偽裝成瀏覽器從網頁拿數據
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0',}resp = requests.get(url=url, headers=headers)print(resp.text.encode('gbk', 'ignore').decode('gbk'))
? 我這里會出現一個編碼的問題 查找資料之后 需要先用 GBK 編碼,加個 ignore 丟棄錯誤的字符,然后再解碼
之后在拿到的網頁源代碼中 老樣子Ctrl+F 檢查爬取的數據是否存在
二. 解析數據 提取數據
OK 接著我們需要從頁面源代碼中提取出我們想要的數據
分析頁面的結構
ex = re.compile(r'<div class="hd">.*?<span class="title">(?P<name>.*?)</span>',re.S)
# 不需要的內容通過.*?過掉 給需要取出的內容 取值為name 類似字典
result = ex.findall(text)# findall返回的是一個列表
# finditer 返回的是一個迭代器 后續需要通過for循環取出
# re.search() 返回的是match對象 需要.group拿數據 只能拿到匹配到的第一個數據
# re.match() 從頭開始匹配 類似^
# 預加載正則表達式 后續可重復使用該正則
# re.complie(r'正則')
繼續編寫正則 想象這是一篇文章 不需要的通過.*?過濾出去 用(.*?)保留下來
后續通過類似 鍵值對取值取出
我們通過迭代器的方式 提取
ex = re.compile(r'<div class="hd">.*?<span class="title">(?P<name>.*?)'r'</span>.*?<p class="">.*?<br>(?P<year>.*?) .*?'r'<span class="rating_num" property="v:average">(?P<judge>.*?)</span>.*?'r'<span>(?P<num>.*?)人評價</span>.*?'r'<p class="quote"><span class="inq">(?P<intro>.*?)。</span></p>',re.S)
result = ex.finditer(text)
for i in result:# 通過.group取數據# 檢驗拿到的數據print(i.group('name'))# 去除前面的空格print(i.group('year').strip())print(i.group('judge'))print(i.group('num'))
三.保存數據 存儲為?csv excel 文件
接著我們保存爬取的數據? 需要用到csv模塊
# 導包
import csvf = open('movie.csv','w',encoding='utf-8',newline='')
# newline 解決空行的問題
csv_writer = csv.writer(f)
# 寫入表頭
csv_writer.writerow(['電影名','年份','評分','評價人數'])
for i in result:# 將數據存儲為字典格式dit = i.groupdict()# 處理年份前的空格dit['year'] = dit['year'].strip()#將值寫入csv文件csv_writer.writerow(dit.values())
# 與with open 不同的是 open需要手動關閉
f.close()
另外一種保存數據的方式 pandas 個人覺得pandas方便很多
以下是實現代碼
?
# 導包
import pandas as pd
# 定義一個空列表 后面將dit字典數據存儲進去
lis = []for i in result:dit = i.groupdict()# 處理年份前的空格dit['year'] = dit['year'].strip()# 只需要改這兩行代碼lis.append(dit)pd.DataFrame(lis).to_excel('movie1.xlsx',index=False)
運行結果如下 如果在excel 中打開此文件 會亂碼 需要將編碼格式寫為 utf-8-sig?
多頁采取的話 需要分析一下 請求的url地址 之后構建個for循環去遍歷
分析二三頁的地址 可得 start參數間隔25?
其實是為了學習正則而采用正則去提取數據 只有在特定的情況下才使用正則 一般使用其它的方法
以下是本次案例的所有代碼 供學習交流使用
import requests
import re
import csvf = open('movie.csv', 'w', encoding='utf-8-sig',newline='')
csv_writer = csv.writer(f)
csv_writer.writerow(['電影名', '年份', '評分', '評價人數'])
for page in range(0, 250, 25):url = f'https://movie.douban.com/top250?start={page}&filter='headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0',}resp = requests.get(url=url, headers=headers)text = resp.text.encode('gbk', 'ignore').decode('gbk')ex = re.compile(r'<div class="hd">.*?<span class="title">(?P<name>.*?)'r'</span>.*?<p class="">.*?<br>(?P<year>.*?) .*?'r'<span class="rating_num" property="v:average">(?P<judge>.*?)</span>.*?'r'<span>(?P<num>.*?)人評價</span>.*?', re.S)result = ex.finditer(text)for i in result:dit = i.groupdict()# 處理年份前的空格dit['year'] = dit['year'].strip()csv_writer.writerow(dit.values())