1. 程式人生 > 實用技巧 >Python爬蟲——爬取豆瓣top250完整程式碼

Python爬蟲——爬取豆瓣top250完整程式碼

# -*- coding = utf-8 -*-

# 解析網頁
from bs4 import BeautifulSoup as bf
# 正則表示式
import re
# Excel表格操作
import xlwt
# 獲取URL得到html檔案
import urllib.request as req

# 設定單獨全域性變數,如需更加規範,也可以將電影資訊封裝成一個class類 比如 class Movie: ...
# 電影名稱
find_name = re.compile(r'<span class="title">(.*?)</span>')
# 電影播放地址連結
find_link = re.compile(r'<a href="(.*?)">') # 電影封面的地址連結,re.S讓換行符包含在字元中 find_imgSrc = re.compile(r'<img.*src="(.*?)"', re.S) # 電影評分 find_score = re.compile(r'<span class="rating_num".*>(.*?)</span>') # 評分人數 find_num = re.compile(r'<span>(\d*人)評價</span>') # 名句 find_inq = re.compile(r'
<span class="inq">(.*?)</span>') # 有些電影沒有某些項,所以查詢長度為0的時候,設定該項為空 def set_film(file, content): # 檢查查詢內容的長度,如果不為0,說明查詢到內容,則將內容轉換成字串型別 if len(re.findall(file, content)) != 0: film = str(re.findall(file, content)[0]) else: film = "" return film # 儲存獲取的html,避免出現ip異常的情況
def write_html(path, html): file = open(path, 'w', encoding='utf-8') file.write(str(html)) file.close() # 迴圈獲取所有的html頁面並提取所需資訊儲存到 data_list 列表 def get_data(): # 獲得多有頁面有價值的資訊,然後集中存放與data_list列表中 data_list = [] # 迴圈遍歷,修改?start=起始排行序號,獲取不同分頁的豆瓣top資訊,url分頁格式去豆瓣換頁內容試試 # 例如第一頁第 top 0-24,第二頁是top 25-49條 ?start=25 這個引數,會讓伺服器響應第二頁的25條資訊 for i in range(0, 250, 25): # 使用二進位制讀取,這點很重要,報錯無數次 html = open('Data/html/html' + str(i//25) + '.html', 'rb') # 接下來是逐一解析資料 bs = bf(html, 'html.parser') # 使用標籤 + 屬性組合查詢,查詢<div class="item"></div>的標籤塊 # 注意:class是關鍵字,所以這裡需要使用 class_ 代替 f_list = bs.find_all('div', class_="item") # 使用re.findall(x, s) 或者 x.findall(s)效果一樣 for f in f_list: data = [] # 將正則表示式提取的內容賦值給自定義變數 file_name = set_film(find_name, str(f)) file_num = set_film(find_num, str(f)) file_link = set_film(find_link, str(f)) file_img_src = set_film(find_imgSrc, str(f)) file_score = set_film(find_score, str(f)) file_inq = set_film(find_inq, str(f)) # 將所有需要的資料儲存到data列表 data.append(file_name) data.append(file_score) data.append(file_num) data.append(file_link) data.append(file_img_src) data.append(file_inq) # 寫入data(單條電影資訊)列表,到總的 data_list(所有電影資訊)列表 data_list.append(data) html.close() return data_list # 儲存豆瓣的各頁html檔案 def save_douban_html(base_url): for i in range(0, 250, 25): # 使用基礎地址 'https://movie.douban.com/top250?start=' + 偏移地址如 '25' url = base_url + str(i) # 獲取html儲存在本地,方便之後爬蟲操作,因為頻繁爬取可能被豆瓣發現異常 html = ask_url(url) # 將檔案批量儲存在 Data/html/ 目錄下 i//25 是整除,命名格式如 html0.html html1.html ... write_html('Data/html/html' + str(i//25) + '.html', html) # 獲取html資訊,並返回html資訊 def ask_url(url): # 設定傳給伺服器的header頭部資訊,偽裝自己是正規瀏覽器訪問 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0" } # 用於儲存獲取的html檔案 html = "" # 最好用 try-except 捕捉異常 try: # 封裝一個Request物件,將自定義的頭部資訊加入進去 res = req.Request(url, headers=headers) # 向指定的url獲取響應資訊,設定超時,防止長時間耗在一個頁面 response = req.urlopen(res, timeout=10) # 讀取html資訊,使用decode('utf-8')解碼 html = response.read().decode('utf-8') # 如果出錯,就捕捉報錯資訊並打印出,這裡使用Exception 泛泛的意思一下 except Exception as error: # 出現異常時候,列印報錯資訊 print("Ask_url is Error : " + error) # 將獲得的html頁面資訊返回 return html # 以下split、main兩個函式和 if __name__ 程式主入口是我個人程式設計習慣,與上述內容無本質關聯 # 定義分隔線長度,並返回分割線字串 def split(num): str1 = "" for i in range(1, num): # print("------------", end='') str1 += "------------" return str1 # 讀取檔案文字 def read_file(file_name): # 開啟文字選擇讀模式 file = open(file_name, 'r', encoding='utf-8') print(file.read()) file.close() # 儲存資料到txt文字中 def save_data_txt(datas, save_file): # 開啟文字選擇寫模式,並指定編碼格式 file = open(save_file, 'w', encoding='utf-8') # 不能直接寫入list,所以通過遍歷一條條寫入 for data in datas: for dat in data: file.write(dat + '\n') file.write(split(10) + '\n') file.close() # 設定excel的單元格字型樣式 def set_font(bold, size, horz): # 建立xlwt格式物件 style_font = xlwt.XFStyle() # 設定字型是否為粗體 style_font.font.bold = bold # 設定字型尺寸大小 style_font.font.height = size # 字型是否居中 if horz: # 設定字型水平居中 style_font.alignment.horz = 0x02 # 設定字型垂直居中 style_font.alignment.vert = 0x01 # 設定單元格自動換行 style_font.alignment.wrap = False # 返回設定的字型樣式 return style_font # 儲存資料到excel檔案中 def save_data_excel(datas, save_path): # 建立一個xlwt物件,使用utf-8編碼格式 excel = xlwt.Workbook(encoding='utf-8') # 建立一個工作表,命名為top250 sheet = excel.add_sheet('top250') # 設定前六列的列寬 width_c = [256*20, 256*6, 256*12, 256*42, 256*72, 256*68] for i in range(0, 6): sheet.col(i).width = width_c[i] # 設定三種單元格樣式 set_font(粗體,尺寸,居中) style_font_title = set_font(True, 240, True) style_font_content = set_font(False, 220, True) style_font_content1 = set_font(False, 220, False) # 表格各列的列名 titles = ['電影名稱', '評分', '評論數', '電影連結', '圖片連結', '電影名言'] index = 0 # 將標題寫入excel for title in titles: # (單元格行序號,單元格列序號,單元格的內容,單元格樣式) sheet.write(0, index, title, style_font_title) index += 1 # 將資料寫入excel index_r = 1 # 從多條電影中每次取出一條 for data in datas: index_c = 0 # 從一條電影中每次取出一個屬性 for item in data: # 前三列設定居中對齊 if index_c <= 2: sheet.write(index_r, index_c, item, style_font_content) # 後三列設定預設對齊,即左對齊 else: sheet.write(index_r, index_c, item, style_font_content1) index_c += 1 index_r += 1 # 儲存excel檔案到指定路徑 excel.save(save_path) # 呼叫測試程式 def main(): base_url = "https://movie.douban.com/top250?start=" # 1.爬取網頁 # 從豆瓣上獲取html檔案並儲存到本地目錄下,該方法成功執行一次即可,儲存html,接下來本地操作 # save_douban_html(base_url) # 2.解析資料 # 逐個解析儲存在本地的html檔案 datas = get_data() # 3.儲存資料 # 儲存爬取資料到本地txt檔案 # save_txt_path = 'Data/Text/top250.txt' # save_data_txt(datas, save_txt_path) # 將讀取的txt文字列印到控制檯 # read_file('Data/Text/top250.txt') # 儲存爬取資料到本地excel檔案 save_excel_path = 'Data/excel/top250.xls' save_data_excel(datas, save_excel_path) # 列印自定義分界線 print(split(10)) # 主程式入口 if __name__ == '__main__': main()