1. 程式人生 > >python抓取豆瓣電影top250資訊

python抓取豆瓣電影top250資訊

1、本博文中程式碼是轉載內容,原文章地址如下:

https://blog.csdn.net/submit66/article/details/78631342?utm_source=blogxgwz1

2、只是在原文程式碼的基礎上稍作修改,添加了一些註釋及無關緊要的程式碼

3、本篇博文涉及知識點如下:

  • ①建立類、建立函式
  • ②建立新執行緒
  • ③用瀏覽器檢查網頁元素
  • ④使用BeautifulSoup獲取網頁內容
  • ⑤儲存網頁文字內容到本地檔案
  • ⑥下載圖片
  • ⑦時間戳

4、程式碼功能為獲取“豆瓣電影top250”頁面的摘要資訊,詳細程式碼如下(執行環境:win7 + python3)

import requests
from   bs4 import BeautifulSoup
import time
import os
import threading

'''
    定義一個類,屬性包含圖片的序號、名稱以及下載的url
'''
class Picture:
    def __init__(self,pic_num,pic_name,pic_url):
        self.pic_name = pic_name
        self.pic_url = pic_url
        self.pic_num = pic_num

'''
下載圖片,因為他比較耗時,所以將其放在子執行緒中
'''
def download_picture(pic_list): #設定圖片儲存的目錄,雙反斜槓\\表示轉義“\”,實際的作用相當於'douban\pic\' file_dir = "douban\pic\\" #如果目錄不存在,就建立它 if not os.path.isdir(file_dir): os.makedirs(file_dir) #下載圖片 for index in range(len(pic_list)): try: #獲取圖片列表的單個元素 pic_url =
pic_list[index] #設定圖片的名字,加上路徑是指在路徑下建立圖片 filename = file_dir +str(pic_url.pic_num) + '_' + pic_url.pic_name + ".jpg" # "wb"表示以二進位制寫入檔案 # 此處".content"表示以二進位制形式返回資料,下載圖片及音訊時需用此方式 # 此處的timeout並不是指超過5秒沒下載完圖片就算超時,而是指5秒內伺服器沒有響應連線請求就超時 with open(filename,'wb') as f_open: f_open.write(requests.get(pic_url.pic_url,timeout=5).content) #因為要下載250個圖片,如果長時間等待,看不出程式正常執行,此處每下載10個圖片在終端就提示一次 if pic_url.pic_num % 10 == 0: print("已下載%d張圖片" % (pic_url.pic_num)) except: print("下載失敗!") #pass表示不返回任何錯誤提示 pass print("爬取耗時:",time.time().__float__() - cuttentTime.__float__(),'s') # param 分頁網址的字尾,用於拼接 param = '' # i 圖片下載的個數 i = 1 #時間戳,用於計算程式執行的時間 cuttentTime = time.time() # pic_list 儲存圖片名字及圖片的下載地址 pic_list = [] while True: base_url = 'https://movie.douban.com/top250' + param my_response = requests.get(base_url,timeout = 5) #若頁面返回的狀態碼不是200,則顯示錯誤 my_response.raise_for_status() response_string = my_response.text soup = BeautifulSoup(response_string,'lxml') #所有的電影資訊都在class為grid_view的ol標籤中 ol_article = soup.find('ol',class_='grid_view') #每部電影對應一個li li_list = ol_article.find_all('li') #獲取電影的資訊 for index in range(len(li_list)): div_item_info = li_list[index].find('div',class_='info') div_hd = div_item_info.find('div',class_='hd') div_bd = div_item_info.find('div',class_='bd') title_list = div_hd.find_all('span') #獲取電影名 title_str = div_hd.find('span',class_='title').getText() #獲取電影別名 if div_hd.find('span',class_='other'): alias_title_str = div_hd.find('span',class_='other').getText().\ replace(' ','').replace(' ','').replace('/','',1) #獲取導演、演員、上映年、電影型別等資訊 content_description_str = div_bd.p.getText().replace(' ','\t\t').\ replace(' ','').replace(' / ','/') #獲取評價星級 rating_star = div_bd.div.find_all('span')[1].getText() #獲取評論數量 comment_str = div_bd.div.find_all('span')[3].getText() #獲取一句話影評 if div_bd.find('p',class_='quote'): quote_str = div_bd.find('p',class_='quote').span.getText() #將抓取的資訊存入本地文件 file_dir = "douban\\" if not os.path.isdir(file_dir): os.makedirs(file_dir) filename = file_dir + "douban250.txt" #此處的"encoding='utf-8'",以utf-8編碼建立開啟檔案,為防止寫入檔案編碼錯誤 with open(filename,'a',encoding='utf-8') as f_open: f_open.write("\n第%d個電影--------------------------------------" % (i)) f_open.write("\n\n\t電影名稱:" + title_str) f_open.write("\n\t電影別名:" + alias_title_str) f_open.write("\n\t電影評星:" + rating_star) f_open.write("\n\t評價數量:" + comment_str) f_open.write("\n\t電影一句話總結:" + quote_str) f_open.write("\n\t電影大致內容資訊:" + content_description_str) #獲取圖片資訊 div_pic = li_list[index].find('div',class_='pic') pic_list.append(Picture(i,div_pic.a.img.get('alt'),div_pic.a.img.get('src'))) i += 1 #獲取分頁資訊 div_paginator = soup.find('div',class_='paginator') next_url = div_paginator.find('span',class_='next') #如果沒有link則退出while迴圈,用來判斷已經到達最後一頁 if not next_url.link: break # 獲取link的某個屬性,可以使用get方法 param = next_url.link.get('href') ''' 在所有資料內容爬取完畢後開始一個新的執行緒下載圖片,這裡還非得用threading模組了, 因為它開啟的派生執行緒在執行時候,主執行緒不會退出,直至派生執行緒執行完畢 但是如果派生執行緒被設定為守護執行緒,即設定setDaemon為true的話, 主執行緒退出派生執行緒也就不執行了(但是這個不是我們想要的) 如果直接使用thread模組就會存在主執行緒提前退出派生執行緒無法執行完畢,導致下載失敗的情況 ''' #這裡我不明白原作者為什麼要開啟一個新執行緒去下載圖片,與直接批量下載圖片有什麼區別嗎, # 此問題待以後學習更多執行緒相關的知識後再分析 try: threa_download = threading.Thread(target=download_picture,args=(pic_list,)) threa_download.setDaemon(False) threa_download.start() except: print('Error: unable to start thread')