Python爬蟲——爬取豆瓣top250完整代碼


說在前頭:

  • 本次僅僅只是記錄使用Python網絡爬蟲爬取豆瓣top250排行榜榜單的內容,爬取其它網頁同理,可能爬取難度不同,但步驟類似。
  • 注意:建議把 html 文件先爬取到本地保存,再從本地讀取 html 進行后面的數據解析和保存操作,因為頻繁訪問同一個頁面,可能被網站判定為異常訪問而拒絕該IP訪問資源,連切換為真實瀏覽器訪問都可能會受限。

 

准備工作:

  本次使用豆瓣top250網址:https://movie.douban.com/top250?start=

 

主要步驟:

  • 爬取網頁
    • 服務器返回給我們的是一個html文件,然后瀏覽器解析服務器返回的文件,通過解析呈現出我們平時看到的精彩網頁內容,我們這一步驟要拿的,就是這個服務器返回發給我們的東西
    • 首頁的網址是:https://movie.douban.com/top250 或 https://movie.douban.com/top250?start=
    • 點擊第二頁的網址是:https://movie.douban.com/top250?start=25&filter=
    • 同理第三頁的網址是:https://movie.douban.com/top250?start=50&filter=
    • 不用管filter過濾器,可以發現規律,第page頁的 start=25*(page-1)
    • baseurl = 'https://movie.douban.com/top250?start='  , 然后通過循環讓字符串拼接 url = baseurl + str(i)
    • i = 0, 25, 50, 75 ...... 就可以獲取 top250 其它頁的內容
    • 借助 urllib.request 獲取 html,偽裝成真實瀏覽器的報頭,不然豆瓣會返回 418錯誤(我是茶壺)
    • 獲取html后保存在本地,最好保存在本地,避免每次都訪問,因為頻繁訪問top250有可能被豆瓣標記為異常訪問

 

  • 解析數據
    • 解析保存的html文件,內容都在html文件中,我們要想辦法把所需內容所在的標簽塊找出來,並根據規則找到所需的內容所在位置,把內容提取出來
    • 結束beautifulSoup解析標簽塊,再結合re正則表達式提取所需的內容
    • 將獲取的內容存入列表或者類對象中

 

  • 保存數據
    • 前面已經解析數據並保存在了列表或者對象之中,變量釋放空間就沒了,我們要做的是把東西保存在本地的文件中
    • 保存獲取的內容到本地text,執行文本讀取操作
    • 或者excel,借助xlwt包寫入excel,借助xlrd包讀取excel

 

完整代碼:

# -*- 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()

 

存儲為文本文件 —— top250.txt

 

存儲為excel文件 —— top250.xls

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM