網址:https://500px.com/seanarcher,seanarcher是一個up主的名字
打開這個網址,會發現有好多圖片,具體到每一個圖片的url地址 https://500px.com/photo/273383049/galya-by-sean-archer,其中273383049為圖片的id
使用https://api.500px.com/v1/photos?ids=圖片id,也就是https://api.500px.com/v1/photos?ids=273383049可以訪問每一個圖片的詳情json信息
那是不是可以通過如下思路來獲取圖片信息呢?
1.訪問索引頁,獲得每個圖片的id
2.根據圖片id構造新的url地址,
3.訪問每個圖片的url地址,獲得圖片鏈接
4.使用圖片鏈接下載圖片
我起初也是這樣想的,可以第一步確實現不了,訪問索引頁后獲得的數據中根本就沒有所有的圖片id信息,有關的只有這部分數據,還是在script標簽里,處理這些數據后發現只有50個圖片數據信息.
然后再繼續分析,調試模式到XHR,發現一個有意思的現象
發現這個請求有返回的json數據,是直接從第二頁開始的,總共8頁,photos參數中就是各個圖片的具體信息,跟使用https://api.500px.com/v1/photos?ids=圖片id訪問的結果差不多
但是有一個問題,直接訪問這個地址會報錯:
結合上述的情況分析,可以得到大致的結論: 該網站的 首頁信息是靜態加載的,從第 2 頁開始是采用了 Ajax 動態加載,URL 不同,需要分別進行解析提取。
1.初次請求網站是直接在html中使用script的標簽返回50條數據信息
2.頁面繼續往下拉,使用的是ajax加載頁面的方式,每次加載一頁,又50條數據,直到第8頁圖片信息加載完才結束
3.結合以上分析,差不多也就400多條數據,算是符合要求
那么現在的問題是如何獲取ajax加載出來的數據信息?
很遺憾,我也暫時還沒找到有啥解決的辦法.
唯一想到的笨辦法是使用瀏覽器獲取返回的json數據,保存下來,然后分析這些json數據,從而獲得圖片下載鏈接,進而下載圖片
一:只下載首頁50個圖片
#!/usr/bin/env python # -*- coding: utf-8 -*-
import csv import json import os import re from _md5 import md5 import pymongo import requests from requests.exceptions import RequestException MONGO_URL = 'localhost' MONGO_DB = 'maoyan' MONGO_TABLE = 'gril' client = pymongo.MongoClient(MONGO_URL, connect=False) db = client[MONGO_DB] def get_one_page(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0' } try: response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: return None except RequestException: print('請求失敗') return None def parse_one_page(html): pattern = re.compile("<script id='bootstrap_data'>.*?{}.*?App.bootstrap = (.*?)</script>", re.S | re.M) items = re.findall(pattern, html) image_data = json.loads(items[0])['userdata']['photos'] # print(image_data)
# print(type(image_data))
for i in range(len(image_data)): yield { 'id': image_data[i]['id'], 'name': image_data[i]['name'], 'taken_at': image_data[i]['taken_at'], 'image_url': image_data[i]['image_url'][-3], # 圖片鏈接有多種大小格式,選擇格式最大的
} # 數據存儲到csv
def write_to_file3(item): with open('gril.csv', 'a', encoding='utf_8_sig', newline='') as f: # 'a'為追加模式(添加)
# utf_8_sig格式導出csv不亂碼
fieldnames = ['id', 'name', 'taken_at', 'image_url'] w = csv.DictWriter(f, fieldnames=fieldnames) # w.writeheader()
w.writerow(item) # 保存到數據庫中
def save_to_mongo(result): if db[MONGO_TABLE].insert(result): print('Successfully Saved to Mongo', result) return True return False # 請求圖片url,獲取圖片二進制數據
def download_image(url): try: response = requests.get(url) if response.status_code == 200: save_image(response.content) # response.contenter二進制數據 response.text文本數據
return None except RequestException: print('請求圖片出錯') return None def save_image(content): file_path = 'D:\\pachong\\gril\\{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(content) def main(): url = 'https://500px.com/seanarcher' html = get_one_page(url) for item in parse_one_page(html): # 只有50個圖片,實際有400多個,還有待進一步研究
# write_to_file3(item) # 保存到csv文件
# save_to_mongo(item) # 保存到數據庫
download_image(item['image_url']) if __name__ == '__main__': main()
效果截圖:
二:獲取剩余圖片
復制其他也返回的json數據,構造如下形式:
def parse_page_detail(data): image_data = data['photos'] for i in range(len(image_data)): yield { 'image_url': image_data[i]['image_url'][-3], # 圖片鏈接有多種大小格式,選擇格式最大的
} # 請求圖片url,獲取圖片二進制數據
def download_image(url): try: response = requests.get(url) if response.status_code == 200: save_image(response.content) # response.contenter二進制數據 response.text文本數據
return None except RequestException: print('請求圖片出錯') return None def save_image(content): file_path = 'D:\\pachong\\500px_all\\{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(content) def get_other(data): for item in parse_page_detail(data): download_image(item['image_url']) get_other(data_2) get_other(data_3) get_other(data_4) get_other(data_5) get_other(data_6) get_other(data_7) get_other(data_8)
實際效果:
