1. 程式人生 > >Python自定義豆瓣電影種類,排行,點評的爬取與儲存(進階上)

Python自定義豆瓣電影種類,排行,點評的爬取與儲存(進階上)

Python 2.7
IDE Pycharm 5.0.3
Firefox 47.0.1

想了想,還是稍微人性化一點,做個成品GUI出來

起因

沒辦法,在知乎預告了要做個GUI出來,吹的牛逼總得自己填坑,下次一定要慎重啊,話說也複習了一下GUI操作。。。。其實就是以前寫的改改,換換輸入輸出而已,so ,don’t worry,Let’s do this!

目的

1.在Python自定義豆瓣電影種類,排行,點評的爬取與儲存(初級)的基礎上,增加了GUI介面(我嘴欠的),減少自己的鍵盤輸入,多選用點選操作。
2.保留1特性的基礎上,選擇載入評論選項,把短評和長評都放在一起,修改了程式碼結構,擴充套件性更好(自認為),方便以後增加爬取主題時候的規範性制定
3.當然最後還是要打包成exe啦,不然怎麼造福小夥伴呢,如何打包還是請見

如何將python打包成exe檔案

方案

使用Tkinter+PhantomJS+Selenium+Firefox實現

實現過程

1.get到首頁後,根據選擇,點選種類,然後根據輸入需求,進行排序 –這裡的輸入時listbox中值的點選鍵入
2.抓取每個電影及超連結,進入超連結後,抓取當前電影的熱評及長評
3.當用戶所要求TOP數目大於第一頁的20個時候,點選載入更多,再出現20個電影,重複2操作。
4.將輸出寫入輸出框架中,寫入txt中等操作

實現效果

py檔案實現效果–TV目前還未實現,即使點了也是電影

這裡寫圖片描述
這裡寫圖片描述

打包成exe檔案執行效果

這裡寫圖片描述

如果不想要cmd視窗,只要GUI,那麼在進行打包的時候請使用-w引數,

pyinstaller -F -w Selenium_PhantomJS_doubanMvGUI.py

程式框架

直接上那麼長的程式可能蒙圈,所以畫了個簡圖
這裡寫圖片描述

至於內部如何巢狀,懶得畫圖了,這幾個模組大概知道就可以讀程式了,程式很簡單的。。。

程式碼

# -*- coding: utf-8 -*-
#Author:哈士奇說喵
#爬豆瓣高分電影及hot影評GUI版本

from selenium import webdriver
import selenium.webdriver.support.ui as ui
import time
from Tkinter import
* print "---------------system loading...please wait...---------------" #獲取電影名及URL def getURL_Title(): global save_name SUMRESOURCES=0 url="https://movie.douban.com/" driver_item=webdriver.Firefox() wait = ui.WebDriverWait(driver_item,15) #構建對應字典,方便鍵入值得對應關係查詢 Kind_Dict={'Hot':1,'Newest':2,'Classics':3,'Playable':4,'High Scores':5, 'Wonderful but not popular':6,'Chinese film':7,'Hollywood':8, 'Korea':9,'Japan':10,'Action movies':11,'Comedy':12,'Love story':13, 'Science fiction':14,'Thriller':15,'Horror film':16,'Whatever':17} #最後一個電影老是在變啊,艹 Sort_Dict={'Sort by hot':1,'Sort by time':2,'Sort by score':3} Ask_Dict={'No film reviews':0,'I like film reviews':1} #鍵入的值對應 kind=Kind_Dict[Kind_Select.get(Kind_Select.curselection()).encode('utf-8')] sort = Sort_Dict[Sort_Select.get(Sort_Select.curselection()).encode('utf-8')] number = int(input_Top.get()) ask_comments = Ask_Dict[Comment_Select.get(Comment_Select.curselection()).encode('utf-8')] save_name=input_SN.get() Ans.insert(END,"#####################################################################") Ans.insert(END," Reloading ") Ans.insert(END,",#####################################################################") Ans.insert(END,"---------------------------------------system loading...please wait...------------------------------------------") Ans.insert(END,"----------------------------------------------crawling----------------------------------------------") Write_txt('\n##########################################################################################','\n##########################################################################################',save_name) print "---------------------crawling...---------------------" ############################################################################## #進行網頁get後,先進行電影種類選擇的模擬點選操作,然後再是排序方式的選擇 #最後等待一會,元素都載入完了,才能開始爬電影,不然元素隱藏起來,不能被獲取 #wait.until是等待元素載入完成! ############################################################################## #選完引數後,開始爬操作 driver_item.get(url) wait.until(lambda driver: driver.find_element_by_xpath("//div[@class='fliter-wp']/div/form/div/div/label[%s]"%kind)) driver_item.find_element_by_xpath("//div[@class='fliter-wp']/div/form/div/div/label[%s]"%kind).click() wait.until(lambda driver: driver.find_element_by_xpath("//div[@class='fliter-wp']/div/form/div[3]/div/label[%s]"%sort)) driver_item.find_element_by_xpath("//div[@class='fliter-wp']/div/form/div[3]/div/label[%s]"%sort).click() num=number+1#比如輸入想看的TOP22,那需要+1在進行操作,細節問題 time.sleep(2) #開啟幾次“載入更多” num_time = num/20+1 wait.until(lambda driver: driver.find_element_by_xpath("//div[@class='list-wp']/a[@class='more']")) for times in range(1,num_time): time.sleep(2) driver_item.find_element_by_xpath("//div[@class='list-wp']/a[@class='more']").click() #print '點選\'載入更多\'一次' #使用wait.until使元素全部載入好能定位之後再操作,相當於try/except再套個while把 for i in range(1,num): wait.until(lambda driver: driver.find_element_by_xpath("//div[@class='list']/a[%d]"%num)) list_title=driver_item.find_element_by_xpath("//div[@class='list']/a[%d]"%i) print '----------------------------------------------'+'NO' + str(SUMRESOURCES +1)+'----------------------------------------------' print u'電影名: ' + list_title.text print u'連結: ' + list_title.get_attribute('href') #print unicode碼自動轉換為utf-8的 #list_title.text是unicode碼,需要重新編碼再寫入txt list_title_wr=list_title.text.encode('utf-8') list_title_url_wr=list_title.get_attribute('href') #寫入gui的輸出框中 Ans.insert(END,'\n------------------------------------------------'+'NO' + str(SUMRESOURCES +1)+'----------------------------------------------',list_title_wr,list_title_url_wr) #寫入txt中 Write_txt('\n----------------------------------------------'+'NO' + str(SUMRESOURCES +1)+'----------------------------------------------','',save_name) Write_txt(list_title_wr,list_title_url_wr,save_name) SUMRESOURCES = SUMRESOURCES +1 #獲取具體內容和評論。href是每個超連結也就是資源單獨的url try: getDetails(str(list_title.get_attribute('href')),ask_comments) except: print 'can not get the details!' #爬完資料後關閉瀏覽器,只保留GUI進行下一步操作 driver_item.quit() ############################################################################## #當選擇一部電影后,進入這部電影的超連結,然後才能獲取 #同時別忽視元素載入的問題 #在載入長評論的時候,注意模擬點選一次小三角,不然可能會使內容隱藏 ############################################################################## def getDetails(url,comments): driver_detail = webdriver.PhantomJS(executable_path="phantomjs.exe") wait1 = ui.WebDriverWait(driver_detail,15) driver_detail.get(url) wait1.until(lambda driver: driver.find_element_by_xpath("//div[@id='link-report']/span")) drama = driver_detail.find_element_by_xpath("//div[@id='link-report']/span") print u"劇情簡介:"+drama.text drama_wr=drama.text.encode('utf-8') #寫入gui的輸出框中 Ans.insert(END,drama_wr) #寫入到txt Write_txt(drama_wr,'',save_name) #載入評論 if comments == 1: print "--------------------------------------------Hot comments TOP----------------------------------------------" #載入四個短評 for i in range(1,5): try: comments_hot = driver_detail.find_element_by_xpath("//div[@id='hot-comments']/div[%s]/div/p"%i) print u"最新熱評:"+comments_hot.text comments_hot_wr=comments_hot.text.encode('utf-8') Ans.insert(END,"--------------------------------------------Hot comments TOP%d----------------------------------------------"%i,comments_hot_wr) Write_txt("--------------------------------------------Hot comments TOP%d----------------------------------------------"%i,'',save_name) Write_txt(comments_hot_wr,'',save_name) except: print 'can not caught the comments!' #嘗試載入長評 try: driver_detail.find_element_by_xpath("//img[@class='bn-arrow']").click() #wait.until(lambda driver: driver.find_element_by_xpath("//div[@class='review-bd']/div[2]/div/div")) time.sleep(1) #解決載入長評會提示劇透問題導致無法載入 comments_get = driver_detail.find_element_by_xpath("//div[@class='review-bd']/div[2]/div") if comments_get.text.encode('utf-8')=='提示: 這篇影評可能有劇透': comments_deep=driver_detail.find_element_by_xpath("//div[@class='review-bd']/div[2]/div[2]") else: comments_deep = comments_get print "--------------------------------------------long-comments---------------------------------------------" print u"深度長評:"+comments_deep.text comments_deep_wr=comments_deep.text.encode('utf-8') #寫入gui的輸出框中 Ans.insert(END,"--------------------------------------------long-comments---------------------------------------------\n",comments_deep_wr) Write_txt("--------------------------------------------long-comments---------------------------------------------\n",'',save_name) Write_txt(comments_deep_wr,'',save_name) except: print 'can not caught the deep_comments!' ############################################################################## #將print輸出的寫入txt中檢視,也可以在cmd中檢視,換行符是為了美觀 ############################################################################## def Write_txt(text1='',text2='',title='douban.txt'): with open(title,"a") as f: for i in text1: f.write(i) f.write("\n") for j in text2: f.write(j) f.write("\n") def Clea():#清空函式 input_Top.delete(0,END)#這裡entry的delect用0 input_SN.delete(0,END) Ans.delete(0,END)#text中的用0.0 root=Tk() root.title('豆瓣影視抓取器beta--by哈士奇說喵') #------------------------------------------輸入框架-------------------------------------- frame_select=Frame(root) title_label=Label(root,text='豆瓣影視TOP抓取器') title_label.pack() #---------------選擇電影/電視劇------------------- Mov_Tv=Listbox(frame_select,exportselection=False,width=9,height=4) list_item1 = ['Movies','TV'] for i in list_item1: Mov_Tv.insert(END,i) scr_MT = Scrollbar(frame_select) Mov_Tv.configure(yscrollcommand = scr_MT.set) scr_MT['command']=Mov_Tv.yview #---------------選擇電影/電視劇 種類------------------- Kind_Select=Listbox(frame_select,exportselection=False,width=12,height=4) list_item2 = ['Hot','Newest','Classics','Playable','High Scores', 'Wonderful but not popular','Chinese film','Hollywood', 'Korea','Japan','Action movies','Comedy','Love story', 'Science fiction','Thriller','Horror film','Whatever'] for i in list_item2: Kind_Select.insert(END,i) scr_Kind = Scrollbar(frame_select) Kind_Select.configure(yscrollcommand = scr_Kind.set) scr_Kind['command']=Kind_Select.yview #---------------選擇電影/電視劇 排序方式------------------- Sort_Select=Listbox(frame_select,exportselection=False,width=12,height=4) list_item3 = ['Sort by hot','Sort by time','Sort by score'] for i in list_item3: Sort_Select.insert(END,i) scr_Sort = Scrollbar(frame_select) Sort_Select.configure(yscrollcommand = scr_Sort.set) scr_Sort['command']=Sort_Select.yview #---------------選擇電影/電視劇 是否載入評論------------------- Comment_Select=Listbox(frame_select,exportselection=False,width=16,height=4) list_item4 = ['No film reviews','I like film reviews'] for i in list_item4: Comment_Select.insert(END,i) scr_Com = Scrollbar(frame_select) Comment_Select.configure(yscrollcommand = scr_Com.set) scr_Com['command']=Comment_Select.yview #---------------選擇電影/電視劇 選擇TOP數------------------- Label_TOP=Label(frame_select, text='TOP(xx)', font=('',10)) var_Top = StringVar() input_Top = Entry(frame_select, textvariable=var_Top,width=8) #---------------選擇電影/電視劇 儲存路徑------------------- Label_SN=Label(frame_select, text='SAVE_NAME(xx.txt)', font=('',10)) var_SN = StringVar() input_SN = Entry(frame_select, textvariable=var_SN,width=8) #----------------------------------------------輸出框架----------------------------------------- frame_output=Frame(root) out_label=Label(frame_output,text='Details') Ans = Listbox(frame_output,selectmode=MULTIPLE, height=15,width=80)#text也可以,Listbox好處在於換行 #點選crawl_button就進入getURL_Title(),點選clear_button就進入Clea() crawl_button = Button(frame_output,text='crawl', command=getURL_Title) clear_button = Button(frame_output,text='clear', command=Clea) #縱向拖拽 scr_Out_y = Scrollbar(frame_output) Ans.configure(yscrollcommand = scr_Out_y.set) scr_Out_y['command']=Ans.yview #橫向拖拽 scr_Out_x = Scrollbar(frame_output,orient='horizontal')#ans x Ans.configure(xscrollcommand = scr_Out_x.set) scr_Out_x['command']=Ans.xview #----------------------------------------------顯示框架----------------------------------------- #----------------選擇框架顯示-------------- frame_select.pack() #影視框架顯示 Mov_Tv.pack(side=LEFT) scr_MT.pack(side=LEFT) #種類框架顯示 Kind_Select.pack(side=LEFT) scr_Kind.pack(side=LEFT) #排序框架顯示 Sort_Select.pack(side=LEFT) scr_Sort.pack(side=LEFT) #評論框架顯示 Comment_Select.pack(side=LEFT) scr_Com.pack(side=LEFT) #TOP輸入 Label_TOP.pack() input_Top.pack() #SAVE NAME輸入 Label_SN.pack() input_SN.pack() #----------------輸出框架顯示-------------- frame_output.pack() out_label.pack() crawl_button.pack(side=LEFT) clear_button.pack(side=RIGHT) scr_Out_y.pack(side=RIGHT) Ans.pack() scr_Out_x.pack() #----------------根框架顯示-------------- root.mainloop()

程式碼就不解釋了。好好看下備註就ok了

問題及解決&Tips

drama_wr=drama.text.encode('utf-8')
Write_txt(drama_wr,'',save_name)

2.出現“提示:這篇影評可能劇透”,獲取長評失敗(上篇已修復),如圖

這裡寫圖片描述

問題出在這條語句上

comments_deep=driver_detail.find_element_by_xpath("//div[@class='review-bd']/div[2]/div
")

2.解決方案,分析網頁元素,看看到底誰在搞鬼;

這裡寫圖片描述

ok,一看就知道,是我們的標籤平白無故多了個div,好辦,直接寫個判斷語句填上

#解決載入長評會提示劇透問題導致無法載入
            comments_get = driver_detail.find_element_by_xpath("//div[@class='review-bd']/div[2]/div")
            if comments_get.text.encode('utf-8')=='提示: 這篇影評可能有劇透':
                comments_deep=driver_detail.find_element_by_xpath("//div[@class='review-bd']/div[2]/div[2]")
            else:
                comments_deep = comments_get

3.Kind有17個選項類別,一個個寫if語句好心煩,好冗餘,比如這樣,要寫17個

if Kind_Select.get(Kind_Select.curselection()).encode('utf-8')=='Movies':
        kind = 1

3.解決方案;用字典啊!!!!!!鍵值對應的除了字典還有更好的麼???以Kind鍵入為例

#構建對應字典,方便鍵入值得對應關係查詢
    Kind_Dict={'Hot':1,'Newest':2,'Classics':3,'Playable':4,'High Scores':5,
              'Wonderful but not popular':6,'Chinese film':7,'Hollywood':8,
              'Korea':9,'Japan':10,'Action movies':11,'Comedy':12,'Love story':13,
              'Science fiction':14,'Thriller':15,'Horror film':16,'Whatever':17}
    #最後一個電影老是在變啊,艹
    kind=Kind_Dict[Kind_Select.get(Kind_Select.curselection()).encode('utf-8')]

4.目前只做了電影的抓取,電視劇那個還沒做,我只是放在上面而已,所以請測試時候不要點選“Tv”選項,裡面沒東西的,我以後,要是有空,應該會把它補全的。挖坑挖坑0.0

一個奇怪的問題

打包之後的檔案,對某些電影抓不了長評,我已排除程式問題,原打包程式在py環境下執行可用,但是exe有的長評就抓不了。。。目前無解
請看圖,以盜夢空間為例
這裡寫圖片描述

但是一樣的程式,在py下執行時可以抓到長評的
這裡寫圖片描述

這個我實在無解,可能是pyinstaller的bug吧

EXE成品檔案下載

最後

測試時間花了挺多的,主要是selenium效率有點低,而且firefox資源佔用太高,對海量資料抓取不是十分有利啊。有誰知道怎麼抓海量動態資料麼?知道的話請留言一下咯

PS

各省被水淹沒,哈爾濱也終於下大雨了,大家出行注意安全–話說我還回去的家麼。。。
這裡寫圖片描述

致謝

相關推薦

Python定義豆瓣電影種類排行點評儲存

Python 2.7 IDE Pycharm 5.0.3 Firefox 47.0.1 想了想,還是稍微人性化一點,做個成品GUI出來 起因 沒辦法,在知乎預告了要做個GUI出來,吹的牛逼總得自己填坑,下次一定要慎重啊,話說也複習了一下G

【原創】python學習筆記1-- 自學爬蟲備註--先佔坑

  Request:使用者將自己的資訊通過瀏覽器(socket client)傳送給伺服器(socket server) Response:伺服器接收請求,分析使用者發來的請求資訊,然後返回資料(返回的資料中可能包含其他連結,如:圖片,js,css等) ps:瀏覽器在接收Res

HenCoder Android 定義 View 1-7:屬性動畫 Property Animation

這期是 HenCoder 自定義繪製的第 1-7 期:屬性動畫(進階篇) 簡介 上期的內容,對於大多數簡單的屬性動畫場景已經夠用了。這期的內容主要針對兩個方面: 針對特殊型別的屬性來做屬性動畫; 針對複雜的屬性關係來做屬性動畫。 TypeEvaluator

定義PopupWindow並且設定背景色變暗的2種方法蒙層效果

private Context context;private TextView tv, tv_1, tv_2, tv_3;private PopupWindow mPopupWindow;private RelativeLayout rl_out;@Overrideprotected void onCrea

Android:定義ImageView展示大圖中的指定區域並切圓角雪碧圖

@Override protected void onDraw(Canvas canvas) { Drawable drawable = getDrawable(); if (drawable instanceof BitmapDrawable)

Mysql 入門增刪改查

bsp com pre sco height name 數據 mysql from 主要已以下兩個表students與students_score,進行數據的增刪改查操作! 1、SELECT 1)select id,tel from students

Python---面向對象第三彈

python對象 one iss pri each super left connect ext  Python對象中一些方法 一、__str__ class Teacher: def __init__(self,name,age): self.name

python 面向對象

關心 __iter__ nvi class nic 詳情 mit remove 類名 類的成員 類的成員可以分為三大類:字段、方法和屬性 註:所有成員中,只有普通字段的內容保存對象中,即:根據此類創建了多少對象,在內存中就有多少個普通字段。而其他的成員,則都是保存在類中,

Python爬蟲 - 網頁文字資訊並儲存美文的儲存

 本篇文章所包含的主要內容:  使用requests模組實現對網頁以字串的形式儲存 使用open()、write()、close()函式實現檔案的開啟與寫入 使用if() 條件語句對所需要的文字資訊進行過濾以形成一個專用提取函式 &n

影象的讀取顯示儲存基於skimage模組

一 skiamge模組 skimage包的全稱是scikit-image SciKit (toolkit for SciPy) ,它對scipy.ndimage進行了擴充套件,提供了更多的圖片處理功能。它是由python語言編寫的,由scipy 社群開發和維護。skimage包由許多的子

python 動態網頁百度圖片

# python 3.6.3 import re import os from urllib import parse from urllib import request ################################################### # 搜尋關鍵字

Python開發【第七篇】:面向物件

上一篇《Python 面向物件(初級篇)》文章介紹了面向物件基本知識: 面向物件是一種程式設計方式,此程式設計方式的實現是基於對 類 和 物件 的使用 類 是一個模板,模板中包裝了多個“函式”供使用(可以講多函式中公用的變數封裝到物件中) 物件,根據模板

python 面向物件

本篇將詳細介紹Python 類的成員、成員修飾符、類的特殊成員。 類的成員 類的成員可以分為三大類:欄位、方法和屬性 注:所有成員中,只有普通欄位的內容儲存物件中,即:根據此類建立了多少物件,在記憶體中就有多少個普通欄位。而其他的成員,則都是儲存在類中,即:無論物件

無業務不伸縮之二雲監控搭配SLB及ESS

雲端計算ESS彈性伸縮課程 無業務不伸縮之二,雲監控搭配SLB及ESS(進階篇) 連載雲端計算文章主題 後續的連載如下1、 無業務不伸縮之一,雲端計算有ESS2、 無業務不伸縮之二,雲監控搭配SLB及ESS3、無互動不加速,雲端計算有CDN4、無對像不儲存,雲端計算有OSS5、無檔案不儲存,雲端計算有”

零基礎掌握百度地圖興趣點獲取POI爬蟲python語言

好,現在進入進階篇教程。 1.獲取昆明市的bounds值 看到下面這個東西了吧?在文字框裡寫入昆明市,或者其他的行政區劃地名,北京市、朝陽區、大河溝子村什麼的。 這也是通過呼叫百度地圖開放平臺API實現的。 實現起來很簡單,把下面這段程式碼複製到一個

Python sys模組

本文針對原文做了少量修改和大量的補充。。。 這篇文章主要介紹了Python標準庫之sys模組使用詳解,講解了使用sys模組獲得指令碼的引數、處理模組、 使用sys模組操作 模組搜尋路徑、使用sys模組查詢內建模組、使用sys模組查詢已匯入的模組,重定向輸出以及重定向錯誤等

python定義異常使用raise引發異常

value init tom 輸入 mar pri Coding pre lis 1.自定義異常類,自定義的異常類必須是Exception或者Error的子類! 1 #!/usr/bin/env python 2 # encoding: utf-8 3 4 cl

Python-定義裝飾器使用裝飾器記錄函式執行次數,一種埋點的實現形式

什麼是裝飾器? 裝飾器本質是一個函式,它可以在不改變原來的函式的基礎上額外的增加一些功能。如常見的@classmethod,@staticmethod等都是裝飾器,接下來記錄下如何自定義個裝飾器: 剛剛說過了,裝飾器的本質就是一個函式,所有想要自定義一個裝飾器,首先自定義一個函式

python定義字典的擴充套件類讓字典操作起來更容易

python自定義的一個字典擴充套件類,可以讓字典操作起來更簡單, 比如: 原來需要這樣用:dic['website'] = 'sharejs.com' 有了這個類,你可以這樣用:dic.websites = 'sharejs.com' 是不是更簡單。 類定義如下 clas

python 爬蟲抓豆瓣電影並存入資料庫

import urllib.request import json import codecs class info(object): #@classmethod def moviedown(url): #網址 url = "https://m