下面的分析相當于一個框架,搞懂之后,對于類似的文字爬取,我們也可以實現。就算不能使用Ajax方法,我們也能夠使用相同思想去爬取我們想要的數據。
?
豆瓣電影排行榜分析
網址:https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0
首先我們打開網頁的審查元素,選中Network==》XHR==》電影相關信息網頁文件
篩選并比較以下數據(三個文件數據)
請求地址
Request 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 Request URL:https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=20 Request URL:https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=40
?
查詢參數
type:movie tag:熱門 sort:recommend page_limit:20 page_start:0type:movie tag:熱門 sort:recommend page_limit:20 page_start:20type:movie tag:熱門 sort:recommend page_limit:20 page_start:40
?
請求報頭
Host:movie.douban.com Referer:https://movie.douban.com/explore User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 X-Requested-With:XMLHttpRequest
?
通過比較請求地址和查詢參數,得出
請求地址 = baseurl+type+tag+sort+page_limit+page_startbaseurl:https://movie.douban.com/j/search_subjects? type:固定為movie tag:關鍵字,需要將utf-8轉換為urlencode sort:固定為recommend page_limit:表示一頁顯示的電影數量,固定20 page_start:表示電影頁數,從0開始,20為公差的遞增函數
?
由此我們獲取到了我們需要的數據,可以將爬蟲分為三步
- 獲取網頁json格式代碼
- 從代碼中獲取電影名和電影海報圖片鏈接
- 將獲得的圖片命名為電影名
?
一 準備工作
在函數外部定義偽裝的請求報頭
headers={'Host': 'movie.douban.com','Referer': 'https://movie.douban.com/explore','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36','X-Requested-With': 'XMLHttpRequest' }
?
二 獲取json格式代碼
def get_page(page):#請求參數params={'type': 'movie','tag': '奧特曼','sort': 'recommend','page_limit': '20','page_start': page,}#基本網頁鏈接base_url = 'https://movie.douban.com/j/search_subjects?'#將基本網頁鏈接與請求參數結合在一起url = base_url + urlencode(params)try:#獲取網頁代碼resp = requests.get(url, headers=headers)print(url)#返回json數據格式代碼if 200 == resp.status_code:print(resp.json())return resp.json()except requests.ConnectionError:return None
?
三 篩選數據
通過觀察電影列表代碼文件的preview,進行數據篩選
def get_image(json):if(json.get('subjects')):data=json.get('subjects')for item in data:title=item.get('title')imageurl=item.get('cover')#返回"信息"字典yield {'title':title,'images':imageurl,}
?
四 存儲圖片文件
def save_page(item):#文件夾名稱file_name = '奧特曼電影大全'if not os.path.exists(file_name):os.makedirs(file_name)#獲取圖片鏈接response=requests.get(item.get('images'))#儲存圖片文件if response.status_code==200:file_path = file_name + os.path.sep + item.get('title') + '.jpg'with open(file_path, 'wb') as f:f.write(response.content)
?
五 多線程處理
def main(page):json = get_page(page)for item in get_image(json):print(item)save_page(item)if __name__ == '__main__':pool = Pool()pool.map(main, [i for i in range(0, 200, 20)])pool.close()pool.join()
?
?
總代碼
?
import requests from urllib.parse import urlencode import os from multiprocessing.pool import Poolheaders={'Host': 'movie.douban.com','Referer': 'https://movie.douban.com/explore','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36','X-Requested-With': 'XMLHttpRequest' }def get_page(page):#請求參數params={'type': 'movie','tag': '奧特曼','sort': 'recommend','page_limit': '20','page_start': page,}#基本網頁鏈接base_url = 'https://movie.douban.com/j/search_subjects?'#將基本網頁鏈接與請求參數結合在一起url = base_url + urlencode(params)try:#獲取網頁代碼resp = requests.get(url, headers=headers)print(url)#返回json數據格式代碼if 200 == resp.status_code:print(resp.json())return resp.json()except requests.ConnectionError:return Nonedef get_image(json):if(json.get('subjects')):data=json.get('subjects')for item in data:title=item.get('title')imageurl=item.get('cover')#返回"信息"字典yield {'title':title,'images':imageurl,}def save_page(item):#文件夾名稱file_name = '奧特曼電影大全'if not os.path.exists(file_name):os.makedirs(file_name)#獲取圖片鏈接response=requests.get(item.get('images'))#儲存圖片文件if response.status_code==200:file_path = file_name + os.path.sep + item.get('title') + '.jpg'with open(file_path, 'wb') as f:f.write(response.content)def main(page):json = get_page(page)for item in get_image(json):print(item)save_page(item)if __name__ == '__main__':pool = Pool()pool.map(main, [i for i in range(0, 200, 20)])pool.close()pool.join()
?
?本來是準備使用https://movie.douban.com/tag/#/?不過在后面,刷新網頁時,總是出現服務器問題。不過下面的代碼還是可以用。
import requests from urllib.parse import urlencode import os from hashlib import md5 from multiprocessing.pool import Poolheaders={'Host': 'movie.douban.com','Referer': 'https://movie.douban.com/tag/','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36', }def get_page(page):params={'sort':'U','range':'0,10','tags':'奧特曼','start': page,}base_url = 'https://movie.douban.com/j/new_search_subjects?'url = base_url + urlencode(params)try:resp = requests.get(url, headers=headers)print(url)if 200 == resp.status_code:print(resp.json())return resp.json()except requests.ConnectionError:return Nonedef get_image(json):if(json.get('data')):data=json.get('data')for item in data:title=item.get('title')imageurl=item.get('cover')yield {'title':title,'images':imageurl,}def save_page(item):file_name='奧特曼大全'+os.path.sep+item.get('title')if not os.path.exists(file_name):os.makedirs(file_name)try:response=requests.get(item.get('images'))if response.status_code==200:file_path = '{0}/{1}.{2}'.format(file_name, md5(response.content).hexdigest(), 'jpg')if not os.path.exists(file_path):with open(file_path, 'wb') as f:f.write(response.content)else:print('Already Downloaded', file_path)except requests.ConnectionError:print('Failed to Save Image')def main(page):json = get_page(page)for item in get_image(json):print(item)save_page(item)if __name__ == '__main__':pool = Pool()pool.map(main, [i for i in range(0, 200, 20)])pool.close()pool.join()
?