日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

转:【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图

發布時間:2024/4/17 python 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转:【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【摘要】 本節中,我們以今日頭條為例來嘗試通過分析Ajax請求來抓取網頁數據的方法。這次要抓取的目標是今日頭條的街拍美圖,抓取完成之后,將每組圖片分文件夾下載到本地并保存下來。

1. 準備工作

在本節開始之前,請確保已經安裝好requests庫。如果沒有安裝,可以參考第1章。

2. 抓取分析

在抓取之前,首先要分析抓取的邏輯。打開今日頭條的首頁http://www.toutiao.com/,如圖6-15所示。

圖6-15 首頁內容

右上角有一個搜索入口,這里嘗試抓取街拍美圖,所以輸入“街拍”二字搜索一下,結果如圖6-16所示。

圖6-16 搜索結果

這時打開開發者工具,查看所有的網絡請求。首先,打開第一個網絡請求,這個請求的URL就是當前的鏈接http://www.toutiao.com/search/?keyword=街拍,打開Preview選項卡查看Response Body。如果頁面中的內容是根據第一個請求得到的結果渲染出來的,那么第一個請求的源代碼中必然會包含頁面結果中的文字。為了驗證,我們可以嘗試搜索一下搜索結果的標題,比如“路人”二字,如圖6-17所示。

圖6-17 搜索結果

我們發現,網頁源代碼中并沒有包含這兩個字,搜索匹配結果數目為0。因此,可以初步判斷這些內容是由Ajax加載,然后用JavaScript渲染出來的。接下來,我們可以切換到XHR過濾選項卡,查看一下有沒有Ajax請求。

不出所料,此處出現了一個比較常規的Ajax請求,看看它的結果是否包含了頁面中的相關數據。

點擊data字段展開,發現這里有許多條數據。點擊第一條展開,可以發現有一個title字段,它的值正好就是頁面中第一條數據的標題。再檢查一下其他數據,也正好是一一對應的,如圖6-18所示。

圖6-18 對比結果

這就確定了這些數據確實是由Ajax加載的。

我們的目的是要抓取其中的美圖,這里一組圖就對應前面data字段中的一條數據。每條數據還有一個image_detail字段,它是列表形式,這其中就包含了組圖的所有圖片列表,如圖6-19所示。

圖6-19 圖片列表信息

因此,我們只需要將列表中的url字段提取出來并下載下來就好了。每一組圖都建立一個文件夾,文件夾的名稱就為組圖的標題。

接下來,就可以直接用Python來模擬這個Ajax請求,然后提取出相關美圖鏈接并下載。但是在這之前,我們還需要分析一下URL的規律。

切換回Headers選項卡,觀察一下它的請求URL和Headers信息,如圖6-20所示。

圖6-20 請求信息

可以看到,這是一個GET請求,請求URL的參數有offset、format、keyword、autoload、count和cur_tab。我們需要找出這些參數的規律,因為這樣才可以方便地用程序構造出來。

接下來,可以滑動頁面,多加載一些新結果。在加載的同時可以發現,Network中又出現了許多Ajax請求,如圖6-21所示。

圖6-21 Ajax請求

這里觀察一下后續鏈接的參數,發現變化的參數只有offset,其他參數都沒有變化,而且第二次請求的offset值為20,第三次為40,第四次為60,所以可以發現規律,這個offset值就是偏移量,進而可以推斷出count參數就是一次性獲取的數據條數。因此,我們可以用offset參數來控制數據分頁。這樣一來,我們就可以通過接口批量獲取數據了,然后將數據解析,將圖片下載下來即可。

3. 實戰演練

我們剛才已經分析了一下Ajax請求的邏輯,下面就用程序來實現美圖下載吧。

首先,實現方法get_page()來加載單個Ajax請求的結果。其中唯一變化的參數就是offset,所以我們將它當作參數傳遞,實現如下:

  • import requests
  • from urllib.parse import urlencode
  • def get_page(offset):
  • params = {
  • 'offset': offset,
  • 'format': 'json',
  • 'keyword': '街拍',
  • 'autoload': 'true',
  • 'count': '20',
  • 'cur_tab': '1',
  • }
  • url = 'http://www.toutiao.com/search_content/?' + urlencode(params)
  • try:
  • response = requests.get(url)
  • if response.status_code == 200:
  • return response.json()
  • except requests.ConnectireplaceString:
  • return None
  • 這里我們用urlencode()方法構造請求的GET參數,然后用requests請求這個鏈接,如果返回狀態碼為200,則調用response的json()方法將結果轉為JSON格式,然后返回。

    接下來,再實現一個解析方法:提取每條數據的image_detail字段中的每一張圖片鏈接,將圖片鏈接和圖片所屬的標題一并返回,此時可以構造一個生成器。實現代碼如下:

  • def get_images(json):
  • if json.get('data'):
  • for item in json.get('data'):
  • title = item.get('title')
  • images = item.get('image_detail')
  • for image in images:
  • yield {
  • 'image': image.get('url'),
  • 'title': title
  • }
  • 接下來,實現一個保存圖片的方法save_image(),其中item就是前面get_images()方法返回的一個字典。在該方法中,首先根據item的title來創建文件夾,然后請求這個圖片鏈接,獲取圖片的二進制數據,以二進制的形式寫入文件。圖片的名稱可以使用其內容的MD5值,這樣可以去除重復。相關代碼如下:

  • import os
  • from hashlib import md5
  • def save_image(item):
  • if not os.path.exists(item.get('title')):
  • os.mkdir(item.get('title'))
  • try:
  • response = requests.get(item.get('image'))
  • 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):
  • with open(file_path, 'wb') as f:
  • f.write(response.content)
  • else:
  • print('Already Downloaded', file_path)
  • except requests.ConnectireplaceString:
  • print('Failed to Save Image')
  • 最后,只需要構造一個offset數組,遍歷offset,提取圖片鏈接,并將其下載即可:

  • from multiprocessing.pool import Pool
  • def main(offset):
  • json = get_page(offset)
  • for item in get_images(json):
  • print(item)
  • save_image(item)
  • GROUP_START = 1
  • GROUP_END = 20
  • if __name__ == '__main__':
  • pool = Pool()
  • groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)])
  • pool.map(main, groups)
  • pool.close()
  • pool.join()
  • 這里定義了分頁的起始頁數和終止頁數,分別為GROUP_START和GROUP_END,還利用了多線程的線程池,調用其map()方法實現多線程下載。

    這樣整個程序就完成了,運行之后可以發現街拍美圖都分文件夾保存下來了,如圖6-22所示。

    圖6-22 保存結果

    最后,我們給出本節的代碼地址:https://github.com/Python3WebSpider/Jiepai。

    通過本節,我們了解了Ajax分析的流程、Ajax分頁的模擬以及圖片的下載過程。

    本節的內容需要熟練掌握,在后面的實戰中我們還會用到很多次這樣的分析和抓取。

    來源:華為云社區 ?作者:崔慶才丨靜覓

    本文老猿轉自:https://blog.csdn.net/devcloud/article/details/95064931,感謝大拿的分享!

    轉載于:https://www.cnblogs.com/LaoYuanPython/p/11166824.html

    總結

    以上是生活随笔為你收集整理的转:【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。