用Ajax爬取今日頭條圖片集
Ajax原理
在用requests抓取頁面時,得到的結果可能和瀏覽器中看到的不一樣:在瀏覽器中可以正常顯示的頁面資料,但用requests得到的結果並沒有。這是因為requests獲取的都是原始 HTML文件,而瀏覽器中頁面
則是經過Ajax處理資料後生成的。這些資料可能在HTML文件中,也可能是經過JavaScript和特定演算法後生成的。
剛開始HTML文件中不包含某些資料,當原始頁面載入完後,會向伺服器傳送Ajax請求獲取資料,這些資料被JavaScript處理形成一些新頁面。
Ajax: 即非同步的JavaScript和XML,是利用JavaScript在保證頁面不重新整理、連結不改變的情況下與伺服器交換資料的並更新
部分網頁的技術。
示例:用Ajax爬取今日頭條圖片
最近想買工裝褲穿,可又不知道怎麼搭配,所以就用爬蟲爬下頭條上工裝褲
的穿搭圖片啦
(1) 獲取網頁頁面的JSON文件
import os import requests from urllib.parse import urlencode#來構造url引數的 from hashlib import md5#用來解析圖片二進位制的 #獲取頁面json def get_page(offest): params={ 'aid':'24', 'offest':offest, 'format':'json', 'keyword':'%E5%B7%A5%E8%A3%85%E8%A3%A4', 'autoload':'true', 'count':'20', 'cur_tab':'1', 'from':'search_tab', 'pd':'synthesis' } url='https://www.toutiao.com/api/search/content/?aid=24&offset=0&format=json&keyword=%E5%B7%A5%E8%A3%85%E8%A3%A4&autoload=true&count=20&cur_tab=1&from=search_tab&pd=synthesis'+urlencode(params) #用urlencode構造url中引數 try: response=requests.get(url) if response.status_code==200:#當請求成功時(status_code=200時)才繼續下面程式碼 return response.json()#用json方法將結果轉化成JSON格式 except requests.ConnectionError: return None
注意:
1)構造Ajax請求時,先探索清楚當前頁面中Ajax請求連結的結構和規律。這裡是Offest改變,其他引數不變。
2)使用urlencode方法構造請求的GET引數
3)發現只有offest發生改變,第一頁0,第二頁20,第三頁40,依次增加20
(2)構造包含圖片連結和標題的字典
#提取圖片url和標題 def parse_page(json): if json.get('data'): for item in json.get('data'):#找到所需資料所處位置 if item.get('title')==None:#執行後發現不是每個item裡都有圖片連結和title,沒有的直接跳過 continue title=item.get('title')#找到標題 print(title) images=item.get('image_list') print(images) for image in images: yield{ 'image':image.get('url'), #找到這個標題下的所以圖片url 形成字典生成器 'title':title }
注意:
1)yield{}方法構造字典生成器非常簡單,快速。
2)用json.get()方法在json文件中找取引數值非常快。
(3)把資料儲存到本地
#實現儲存圖片的方法 def save_image(item): if not os.path.exists(item.get('title')):#建立以標題為名稱的資料夾 os.mkdir(item.get('title')) try: response=requests.get(item.get('image'))#訪問圖片的url if response.status_code==200: file_path='{0}/{1}.{2}'.format(item.get('title'),md5(response.content).hexdigest(),'jpg') if not os.path.exists(file_path):#名稱file_path使用其內容的md5值,可以去除重複 with open(file_path,'wb') as f:#訪問成功後,將其二進位制程式碼存入file_path.jpg中 f.write(response.content) else: print('Already Download',file_path) except requests.ConnectionError: print('Failed to save image')
注意:
1)這裡的item就是(2)中得到的包含url和標題的字典
1)是以二進位制寫的方式存入檔案,'wb'
(4)構造offest 進行遍歷
def main(offest): json=get_page(offest) for item in parse_page(json): print(item) save_image(item) if __name__=='__main__': for i in range(0,4): offest=i*20 main(offest)