用Python爬取中國醫生電影評論生成詞云并實現數據可視化(內附源碼)
今日目標:爬取豆瓣電影中國醫生評論實現數據可視化
前段時間,主旋律電影《中國醫生》上線,大家有沒有去看呢?反正我去看了,有點感人(其實哭得稀里嘩啦)。看完后,內心感概萬分,回到家緩了好久。看了電影的海報畫面,想著可以爬一爬大家對電影的評論,正好給大家寫文了。于是,利用下班時間給大家做了這個爬蟲項目。廢話不多了,直接開整。
開發環境
系統:Windows10 64位
Python版本:Python3.7
IDE:Pycharm
第三方庫:selenium lxml re wordcloud PIL numpy jieba matplotlib
餅圖
餅圖
詞云生成
詞云生成
柱狀圖生成
柱狀圖生成
1 獲取網址規律
可以看到 start 和 status是變化的關鍵
在這個頁面可以通過xpath獲取地址網頁 評論詳情 和評分
地址網頁:
評論詳情:
評分 :
2 打開地址網頁,獲取地址信息
有些沒有地址信息 所有需要獲取全部 后期通過數據處理獲取有地址信息的
3 把獲取的數據進行解析 分別存放三個文件
4 通過讀取相應的文件生成相應的圖表
1 滑塊驗證
這個參考代碼里面的滑塊驗證的方法
通過像素對比找到缺口
移動一段距離 之后速度變化慢慢往前面走 到達缺口就能夠驗證成功
2 切換iframe
# 切換iframe
driver.switch_to.frame(1)
需要切換iframe才能找到滑塊和輸入賬號 密碼 的元素位置
3 顯示等待
wait.until(
EC.presence_of_element_located((By.XPATH, '//*[@id="profile"]/div/div[2]'))
)
等待元素出現才進行下一步的處理
4 數據處理
出現不合法的數據 比如 該用戶已經主動注銷帳號
判斷源代碼中是否存在 如果存在就跳過 防止等待時間過長 退出程序
if driver.page_source.__contains__("`該用戶已經主動注銷帳號`"):continue
5 抓取思維
采取先抓大再抓小
這樣可以確定幾個元素是相對應的
循環的時候會再次使用xpath 此時的xpath寫法
需要加一個 .
item={
"href": email_detail.xpath('./div/a/@href'),
"detail": email_detail.xpath("./div[2]/p/span//text()"),
"rate": email_detail.xpath("./div[2]/h3/span[2]/span[2]/@class")
}
6 json模塊默認編碼
默認:ascii碼 為了中文的正確顯示 需要傳遞參數ensure_ascii
f.write(json.dumps(email, ensure_ascii=False) + ",\n")
7 詞云圖的生成
按照圖片格式只需要添加一個參數即可mask
# graph 圖片對象
word_cloud=WordCloud(font_path="simsun.ttc",
background_color="white",
mask=graph, # 指定詞云的形狀
)
8 柱狀圖和餅圖
難點在于json文件讀取
循環獲取的data 然后通過列表構建echarts需要的數據格式
$.getJSON("json_file/rate.json", function(data) {
var x_data=[];
for (var i=0; i < data.length; i++) {
console.log(data[i]);
for(var key in data[i]){ // 輸出字典元素,如果字典的key是數字,輸出時會自動按序輸出
hello={value: data[i][key], name: key+"星"}
x_data[i]=hello;
}
};
詞云圖
# 詞云生成
import jieba
import numpy as np
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from PIL import Image
text=open("json_file/detail.text",encoding='utf8').read()
text=text.replace('\n',"").replace("\u3000","")
text_cut=jieba.lcut(text)
text_cut=' '.join(text_cut)
# 主要區別
background=Image.open("image/mmexport1626868510673.jpg")
graph=np.array(background)
word_cloud=WordCloud(font_path="simsun.ttc",
background_color="white",
mask=graph, # 指定詞云的形狀
)
word_cloud.generate(text_cut)
plt.subplots(figsize=(12,8))
plt.imshow(word_cloud)
plt.axis("off")
plt.show()
滑塊驗證
def slide(driver):
"""滑動驗證碼"""
# 切換iframe
driver.switch_to.frame(1)
# 找到滑塊
block=driver.find_element_by_xpath('//*[@id="tcaptcha_drag_button"]')
# 找到刷新
reload=driver.find_element_by_xpath('//*[@id="reload"]')
while True:
# 摁下滑塊
ActionChains(driver).click_and_hold(block).perform()
# 移動
ActionChains(driver).move_by_offset(180, 0).perform()
# 獲取位移
tracks=get_tracks(30)
# 循環
for track in tracks:
# 移動
ActionChains(driver).move_by_offset(track, 0).perform()
# 釋放
ActionChains(driver).release().perform()
# 停一下
time.sleep(2)
# 判斷
if driver.title=="登錄豆瓣":
print("失敗...再來一次...")
# 單擊刷新按鈕刷新
reload.click()
# 停一下
time.sleep(2)
else:
break
打開文件獲取清洗數據
def get_file():
# 打開文件獲取清洗數據
f=open('data.json', 'r', encoding="utf-8")
hello=f.read()
# 地址列表 評分列表 評論內容列表
address_=[]
rate_=[]
detail_=[]
# 按換行符進行
for i in hello.split("\n"):
try:
# 轉換為字典
data=eval(i[:len(i) - 1])
# 獲取評論詳細內容
detail=data.get("detail")[0]
# 獲取評分
rate=re.findall("(\d{1})\d", data.get("rate")[0])[0]
# 獲取地址
address=".".join(re.findall("常居: ([\u4e00-\u9fa5]{2})", "".join(data.get("address"))))
# 地址存在則添加到地址列表中
if address:
address_.append(address)
# 把評分添加到評分列表中
rate_.append(rate)
# 把評論添加到評論列表中
detail_.append(detail)
except:
continue
獲取評分和唯一地址
# 獲取評分和地址的唯一
rate_set=set(rate_)
address_set=set(address_)
# 寫入 評分json
with open("json_file/rate.json", 'w', encoding="utf-8") as file:
rate_json_list=[]
for r in rate_set:
# 獲取評分頻次并且構造字典
rate_json={r: rate_.count(r)}
rate_json_list.append(rate_json)
file.write(json.dumps(rate_json_list, ensure_ascii=False))
寫入地址json文件
# 寫入地址json文件
with open("json_file/address.json", 'w', encoding="utf-8") as file:
address_json_list=[]
for a in address_set:
# 獲取地址頻次并且構造字典
address_json={a: address_.count(a)}
address_json_list.append(address_json)
file.write(json.dumps(address_json_list, ensure_ascii=False))
寫入詳情文件夾
# 寫入詳情文件夾
with open("json_file/detail.text", 'w', encoding="utf-8") as file:
detail="".join(detail_).replace("\n", "")
file.write(detail)
def get_json(data, driver, f):
Html=etree.HTML(data)
# 通過xpath獲取響應的板塊
email_details=Html.xpath('//*[@id="comments"]/div')
items=[]
# 循環板塊 獲取每一個板塊里面的數據
for email_detail in email_details:
# 地址頁的地址 評論內容 評分呢
item={
"href": email_detail.xpath('./div/a/@href'),
"detail": email_detail.xpath("./div[2]/p/span//text()"),
"rate": email_detail.xpath("./div[2]/h3/span[2]/span[2]/@class")
}
items.append(item)
循環列表獲取地址網址
# 循環列表獲取地址網址 爬取地址
for email in items:
# 如果網址為控則跳過
if not email.get("href"):
continue
driver.get(email.get("href")[0])
# 如果評論用戶已經注冊則跳過
if driver.page_source.__contains__("該用戶已經主動注銷帳號"):
continue
print(email.get("href"))
wait=WebDriverWait(driver, 10)
# 隱士等待 等待數據板塊出現進行下一步
wait.until(
EC.presence_of_element_located((By.XPATH, '//*[@id="profile"]/div/div[2]'))
)
# 獲取地址
email["address"]=etree.HTML(driver.page_source).xpath('//*[@id="profile"]/div/div[2]/div[1]/div//text()')
# 整體數據寫入初始文件中
f.write(json.dumps(email, ensure_ascii=False) + ",\n")
主程序
def main(user, pwd):
"""主程序"""
f=open("data.json", "w", encoding="utf-8")
f.write("[")
url="https://accounts.douban.com/passport/login"
# 驅動路徑
driver_file=os.path.join(os.path.dirname(__file__), "driver_exe", "chromedriver.exe")
# 聲明驅動
driver=webdriver.Chrome(executable_path=driver_file)
driver.get(url)
driver.find_element_by_xpath('//*[@id="account"]/div[2]/div[2]/div/div[1]/ul[1]/li[2]').click()
driver.find_element_by_xpath('//*[@id="username"]').send_keys(user)
driver.find_element_by_xpath('//*[@id="password"]').send_keys(pwd)
driver.find_element_by_xpath('//*[@id="account"]/div[2]/div[2]/div/div[2]/div[1]/div[4]/a').click()
# 停一下,等待出現
time.sleep(2)
# 滑動驗證碼
slide(driver)
print("成功")
type_mile=["P", "F"]
for type_ in type_mile:
if type_mile=="P":
index_mile=480
else:
index_mile=180
for i in range(0, index_mile, 20):
url=f"https://movie.douban.com/subject/35087699/comments?start={i}&limit=20&status={type_}&sort=new_score"
print(url)
driver.get(url)
# 解析數據
get_json(driver.page_source, driver, f)
f.write("]")
driver.quit()
get_file()
# 所有數據獲取完畢之后推出瀏覽器 解析數據
# 解析完畢并且創建解析之后數據的json文件
f.close()
if __name__=='__main__':
user=input("請輸入你的賬號:")
pwd=input("請輸入你的密碼:")
main(user, pwd)
僅供學習,爬蟲使用需謹慎!
希望可以得到各位的一鍵三連,感謝各位支持!
祝大家學習python順利!
如果有正在跟我一樣的自學的朋友,需要我本篇的代碼或者其他的Python學習資料可以轉發此文私信我(私信發我“中國醫生”)
//CASS11.0亮點功能介紹:
1、此次CASS11全新發布,新功能有CASS3D點云、方格網計算島狀區域土方量和python二次開發。
2、CASS3D支持點云數據的空間三維真實效果顯示以及三維視圖下的矢量化采集功能、分析功能,支持自動生成等高線,支持二三維窗口聯動測圖。
3、CASS11針對各種復雜地形情況以及場地實際要求,優化土石方量計算方法,提供多種土方計算方法,如三角網法、方格網法、斷面法、等高線法等,新增方格網法計算島狀區域土方量。
4、CASS11深度支持python二次開發,支持添加自定義功能命令,打破系統固化壁壘,支持無線擴展。
5、CASS11支持搭載CAD平臺:
AutoCAD平臺:AutoCAD2010-2020
中望CAD平臺:中望CAD2019-2020
浩辰CAD平臺:浩辰CAD2020
6、CASS11安裝包可同時檢測到windows xp/vista/windows7/ windows8/ windows10 32位和64位的CAD。
聯系我給出軟件