經(jīng)過 python爬蟲實戰(zhàn)系列 中的 python3爬蟲系列06之整體架構(gòu)式:根據(jù)關(guān)鍵詞爬取百度圖片 相關(guān)學(xué)習(xí),現(xiàn)在我們已經(jīng)會一些基本的靜態(tài)html頁面的爬蟲了。
接下來開始一些更復(fù)雜和實戰(zhàn)例子;
在前面我們玩了好多靜態(tài)的 HTML ,想必你應(yīng)該知道怎么去爬這些數(shù)據(jù)了,但還有一些常見的動態(tài)數(shù)據(jù),比如:商品的評論數(shù)據(jù),實時的直播彈幕,各類影片的評分等等…
這些數(shù)據(jù)是會經(jīng)常發(fā)生改變的,因此很多網(wǎng)站就會用到 Json 來傳輸這些數(shù)據(jù)
那么遇到 Json 我們應(yīng)該怎么辦呢?
首先要知道python怎么在json格式中獲取到想要的數(shù)據(jù):
python 的 json 模塊有兩個主要的函數(shù):
將 python 對象轉(zhuǎn)化為 json格式: json.dumps()
將json數(shù)據(jù)轉(zhuǎn)化為python對象: json.loads()
具體使用操作可以參考:
python對json對象或json數(shù)組操作以及讀寫各類txt,csv,html,xls文件的工具類
好了,不吹牛皮了,說半天不如實戰(zhàn)。
環(huán)境:
Python版本 :3.6
爬取網(wǎng)頁模塊:requests
分析網(wǎng)頁模塊:json
保存CSV文件
要知道 動態(tài)網(wǎng)頁指的是網(wǎng)頁的內(nèi)容通過js動態(tài)加載出來的數(shù)據(jù)。那么分析一頓是免不了的啦。
本次爬蟲的目標(biāo)是豆瓣電影和電視劇頁面:
URL如下:
https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0
一打開這個頁面我們可以看到,其下方有一個【加載更多】。。
這就是動態(tài)加載的,所以我們無法直接通過get方法獲取網(wǎng)頁內(nèi)容。
所以,當(dāng)我們點擊加載更多時,可以通過開發(fā)者工具(瀏覽器里面按F12打開) Network選項中的XHR 來獲取動態(tài)加載的js。
查看請求,然后haders里面有個url:
打開獲取到的連接:
https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0
可以看到返回的是json數(shù)據(jù):
這里我們就可以嘗試構(gòu)造一個連接,讓它從第一個電影開始,并顯示200個:
https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=200&page_start=0
打開驗證就知道了,
電影的:
電視劇的也一樣:
https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0
然后隨便復(fù)制一下這個頁面里面的一段json數(shù)據(jù)。
打開瀏覽器,在線解析一下這個json:
(你隨便百度一下json在線解析就可以了)
評分rate
電影名稱title
電影的豆瓣鏈接url
封面圖片的地址cover
OK,分析完畢,就開始整代碼了。
因為動態(tài)頁面中,我們看到請求返回的是json數(shù)據(jù),而且有了對應(yīng)的URL地址,所以就不需要再使用什么beautifulsoup 解析器了。
直接將響應(yīng)的json字符串,轉(zhuǎn)為python的字典對象操作就好了。
熱門電影的爬蟲:
rowCount 是對應(yīng)的條數(shù)。
# 熱門電影 def douban_movie(rowCount): url='https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0' # 解決出現(xiàn)403拒絕訪問 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/51.0.2704.63 Safari/537.36'} # 使用request模塊打開并獲取網(wǎng)頁內(nèi)容 response = requests.get(url,headers = headers,verify=False,timeout=30) print(response.text) # 報錯:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) # 解決:以后在使用json時,最好先輸出一下參數(shù),檢查一下是否符合格式? content = response.content # json格式轉(zhuǎn)為字典 result = json.loads(content) print(content,result) # 獲取相關(guān)信息并存入列表的字典中 movie_list = [] mos = result['subjects'] for i in range (0,len(mos)): mo = {} mo['rate']=mos[i]['rate'] mo['cover']=mos[i]['cover'] mo['url']=mos[i]['url'] mo['title']=mos[i]['title'] movie_list.append(mo) # 列表存放字典 return movie_list
熱門電視劇的爬蟲:
rowCount 是對應(yīng)的條數(shù)。
# 熱門電視劇 def douban_tv(rowCount): url='https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0' print(url) # 解決出現(xiàn)403拒絕訪問 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/51.0.2704.63 Safari/537.36'} # 使用request模塊打開并獲取網(wǎng)頁內(nèi)容 response = requests.get(url, headers=headers, verify=False, timeout=30) # 禁止重定向 content = response.text print(content) # 返回的是json,那么就直接解碼轉(zhuǎn)為字典。不需要解析器bs了 result = json.loads(content) tvs = result['subjects'] tv_list = [] # 創(chuàng)建一個列表 for i in range (0,len(tvs)): tv={} # 創(chuàng)建一個字典 tv['rate']=tvs[i]['rate'] # 評分 tv['title']=tvs[i]['title'] # 電影名稱 tv['cover'] = tvs[i]['cover'] # 封面圖片的地址 tv['url'] = tvs[i]['url'] # 電影的豆瓣鏈接 tv_list.append(tv) # 列表存放字典 return tv_list
其實是差不多的,甚至可以簡化到一個函數(shù)去共用。
然后就是保存一下爬取的數(shù)據(jù):
# 保存為csv文件 def output_csv(datalist): print(type(datalist),len(datalist)) # <class 'list'> 100 import csv # 準(zhǔn)備好存儲的csv文件 csv_file = open("douban_data.csv", 'w', newline='', encoding='utf-8-sig') # 解決中文亂碼問題 writer = csv.writer(csv_file) writer.writerow(['評分', '作品名稱', '豆瓣鏈接','封面圖片']) for data in datalist: writer.writerow([data['rate'], data['title'],data['url'],data['cover']]) csv_file.close()
最后呢調(diào)用傳參:
if __name__=="__main__": category = input('請輸入爬取的類別代號(電視?。?,電影:1):') rowCount = input('請輸入爬取的條數(shù):') if category=='0': print('爬取電視劇中,請稍后...') result = douban_tv(rowCount) elif category=='1': print('爬取電影中,請稍后...') result = douban_movie(rowCount) else: print('輸入錯誤,暫不支持,請重試...') # 持久化保存 # for i in result: # print(i) output_csv(result) print("爬蟲完畢,文件已生成??烊ゲ榭窗?quot;)
整個源碼:
#!/usr/bin/python3 #@Readme : 豆瓣熱門電影/電視劇-不需登錄的動態(tài)網(wǎng)頁爬蟲-ajax加載的 # 目標(biāo): https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0 # 返回的是json數(shù)據(jù),那么就不需要解析器了。直接轉(zhuǎn)字典就好了。 import requests import json # 熱門電視劇 def douban_tv(rowCount): url='https://movie.douban.com/j/search_subjects?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0' print(url) # 解決出現(xiàn)403拒絕訪問 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/51.0.2704.63 Safari/537.36'} # 使用request模塊打開并獲取網(wǎng)頁內(nèi)容 response = requests.get(url, headers=headers, verify=False, timeout=30) # 禁止重定向 content = response.text print(content) # 返回的是json,那么就直接解碼轉(zhuǎn)為字典。不需要解析器bs了 result = json.loads(content) tvs = result['subjects'] tv_list = [] # 創(chuàng)建一個列表 for i in range (0,len(tvs)): tv={} # 創(chuàng)建一個字典 tv['rate']=tvs[i]['rate'] # 評分 tv['title']=tvs[i]['title'] # 電影名稱 tv['cover'] = tvs[i]['cover'] # 封面圖片的地址 tv['url'] = tvs[i]['url'] # 電影的豆瓣鏈接 tv_list.append(tv) # 列表存放字典 return tv_list # 熱門電影 def douban_movie(rowCount): url='https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit='+rowCount+'&page_start=0' # 解決出現(xiàn)403拒絕訪問 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/51.0.2704.63 Safari/537.36'} # 使用request模塊打開并獲取網(wǎng)頁內(nèi)容 response = requests.get(url,headers = headers,verify=False,timeout=30) print(response.text) # 報錯:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) # 解決:以后在使用json時,最好先輸出一下參數(shù),檢查一下是否符合格式? content = response.content # json格式轉(zhuǎn)為字典 result = json.loads(content) print(content,result) # 獲取相關(guān)信息并存入列表的字典中 movie_list = [] mos = result['subjects'] for i in range (0,len(mos)): mo = {} mo['rate']=mos[i]['rate'] mo['cover']=mos[i]['cover'] mo['url']=mos[i]['url'] mo['title']=mos[i]['title'] movie_list.append(mo) # 列表存放字典 return movie_list # 保存為csv文件 def output_csv(datalist): print(type(datalist),len(datalist)) # <class 'list'> 100 import csv # 準(zhǔn)備好存儲的csv文件 csv_file = open("douban_data.csv", 'w', newline='', encoding='utf-8-sig') # 解決中文亂碼問題 writer = csv.writer(csv_file) writer.writerow(['評分', '作品名稱', '豆瓣鏈接','封面圖片']) for data in datalist: writer.writerow([data['rate'], data['title'],data['url'],data['cover']]) csv_file.close() if __name__=="__main__": category = input('請輸入爬取的類別代號(電視?。?,電影:1):') rowCount = input('請輸入爬取的條數(shù):') if category=='0': print('爬取電視劇中,請稍后...') result = douban_tv(rowCount) elif category=='1': print('爬取電影中,請稍后...') result = douban_movie(rowCount) else: print('輸入錯誤,暫不支持,請重試...') # 持久化保存 # for i in result: # print(i) output_csv(result) print("爬蟲完畢,文件已生成??烊ゲ榭窗?quot;)
運行一下,爬取結(jié)果:
電視劇