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啦,不然怎麼造福小夥伴呢,如何打包還是請見
方案
使用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