目前學習python幾個月了,因爲本身比較喜歡跑馬拉松,已經跑過了不少場比賽,前些天就寫了個簡單的爬蟲爬取了網上三千多場馬拉松比賽的報名信息。 今年5月27日,我又參加了巴圖魯關門山壹佰越野50千米組的比賽,這裏的「巴圖魯」源自蒙古語「英雄」的意思,這場比賽也是出了名的虐,地點在遼寧省本溪市 · 關門山國家森林公園,累計爬升3655m。當天早上六點準時出發,剛跑沒多久就來了很長一段陡峭的臺階......此處省略一萬字......最終通過不少小時的艱苦奮戰完成了比賽。python
賽後去官網想找幾張好看的圖片發朋友圈,打開官網賽事圖片連接到了愛運動的一個網頁runnerbar.com/yd_runnerba…,這是個單頁面的網頁,不斷滾動會自動加載更多的圖片,我把頁面一點點滾動找了很長一段時間根本找不到個人照片,刷新一下頁面照片又從頭開始了,實在不能忍。因而,我想要不把圖片所有下載到本地查看吧,想幹就幹。git
在chrome瀏覽器裏輸入快捷鍵Cmd + Opt + I(Windows上是F12,或Ctrl + Shift + I),將調試選項切到Network,以下 github
一個個觀察此網頁發送的請求,找到和圖片相關的請求 這是一個get請求,初步分析裏面的參數,activity_id表明賽事id,page和pageSize分別表明頁數和每頁大小,接着將請求放在postman上印證在postman里加了三個參數成功返回了一個json格式的值,第一階段很順利,接着分析裏面的返回值,下面取了其中的一個元素chrome
{
"album": {
"activity_photo_count": 6984,
"searchResultList": [
{
"id": "32926651",
"uid": 50392,
"name": "巴圖魯關東越野",
"user_name": null,
"user_img": "http://oss.runnerbar.com/img/user_upload/origin/20180526/1527305285356_fb59065d_18ce_478b_a3aa_259783f4cd5b.jpg",
"create_time": 1527313780000,
"image_height": 3648,
"image_width": 5472,
"orientation": 1,
"url_hq": "http://oss.runnerbar.com/img/watermark/user_upload/origin/20180526/1527313783392_235c5cea_5d0c_4cd7_afc6_0ba37cdc7c1d.jpg?quality=h",
"url_lq": "http://oss.runnerbar.com/img/watermark/user_upload/origin/20180526/1527313783867_7d986351_fde4_418a_8fb3_1723dcb38aec.jpg",
"content": null,
"is_like": 0,
"like_count": null,
"comment_count": 0
}}
複製代碼
這是個json格式,最外層裏有個album元素,album裏包含了圖片總數量activity_photo_count和圖片信息的數組searchResultList。每張圖片包含了id、uid、user_img、create_time等等,和圖片路徑相關的有三個值分別是user_img、url_hq、url_lq,其中的user_img打開後發現是賽事的宣傳logo,剩下的url_hq、url_lq根據命名就很容易猜測到這是對應的兩種尺寸的圖片,用瀏覽器分別打開,果不其然正是想要的圖片路徑。json
上面已經知道了請求url和參數,下面就是須要將這些用代碼實現出來。首先是發請求數組
url='http://m.yundong.runnerbar.com/yd_mobile/share/album.json'
para = {'activity_id':id,'page':page,'pageSize':100}
header = {}
r = requests.post(url,data=para,headers= header)
複製代碼
請求的返回值是json,json內容在上面已經貼出來了這裏就再也不重複,接着解析這個json瀏覽器
json_r = r.json()
parsed_json = json_r['album']['searchResultList']
activity = {}
items = []
count = json_r['album']['activity_photo_count']
複製代碼
這裏就取到了圖片總數量和圖片信息的數組,這個請求參數是page和pageSize,一個請求只能取到一部分圖片信息並不能把全部的圖片都取出來。那能不能把全部圖片分紅一頁返回呢?因而在postman上作了實驗,將page=1,pageSize=10000發送,結果並非想要的,真正返回的圖片數量是100。說明這個接口作了校驗,每一個分頁最大數量是100。看來投機取巧是不行了,分頁仍是要作的。 首先將單個請求封裝成方法,傳入page返回對應page的圖片信息數組app
def getRaceInfo(id,page):
url='http://m.yundong.runnerbar.com/yd_mobile/share/album.json'
para = {'activity_id':id,'page':page,'pageSize':100}
header = {}
r = requests.post(url,data=para,headers= header)
json_r = r.json()
parsed_json = json_r['album']['searchResultList']
activity = {}
items = []
count = json_r['album']['activity_photo_count']
for item in parsed_json:
# print(item['user_img'])
items.append(item)
activity['items'] = items
activity['count'] = count
return activity
複製代碼
圖片的作數量是count,每頁分100張圖片,起點是第1頁,那麼總的分頁數量就是count/100+2,分頁的代碼就應該是這樣的post
for i in range(1,int(count/100+2)):
data = getRaceInfo(id,i)['items']
複製代碼
這裏只是貼了一小段代碼,完整代碼能夠參見上面的github地址學習
有了圖片在url,下載圖片就更簡單了,直接上代碼
def save_img(img_url,file_name,file_path='book'):
#保存圖片到磁盤文件夾 file_path中,默認爲當前腳本運行目錄下的 book\img文件夾
try:
if not os.path.exists(file_path):
print('文件夾',file_path,'不存在,從新創建')
#os.mkdir(file_path)
os.makedirs(file_path)
#得到圖片後綴
file_suffix = os.path.splitext(img_url)[1]
#拼接圖片名(包含路徑)
filename = '{}{}{}{}'.format(file_path,os.sep,file_name,file_suffix)
#下載圖片,並保存到文件夾中
urllib.request.urlretrieve(img_url,filename=filename)
except IOError as e:
print('文件操做失敗',e)
except HTTPError as e:
print('Error code: ', e.code)
except Exception as e:
print('錯誤 :',e)
複製代碼
運行python,查看本地文件 幾千張圖片很快下載到了本地
這時又有了新的想法,既然能夠下載關門山越野的圖片,是否是能夠把愛運動裏全部的圖片都下載下來,說幹就幹。因而我將賽事id定義成參數,寫個方法遍歷id。改動了幾行重新運行,幾個小時後程序還在運行可是圖片佔用的大小已經超過了7G, 打開文件裏面包含了各個賽事的圖片,眼看圖片愈來愈多加上個人mac存儲空間有限最終中止了下載,可是這個思路應該是可行的。源碼地址: github.com/halibobo/ru…
整個過程從開始到結束都在一天內完成的,代碼裏也沒有什麼複雜的邏輯,但完成以後內心仍是有不少的知足感。
最後貼上一句我很喜歡的賽事宣傳語
和一羣志同道合的人,一塊兒奔跑在理想的路上,
回頭有一路的故事,低頭有堅決的腳步,擡頭有清晰的遠方。
—— 致巴圖魯er
複製代碼