分析Ajax 爬取今日头条图片
1.准备工作
- 安装requests库
2.抓取分析
在搜索入口输入“中秋”二字,打开开发者工具,查看所有网络请求,切换到XHR过滤选项卡,出现一个Ajax请求,点击data字段,发现有许多条数据。点开数据,发现一一对应。
抓取分析
所要抓取的图片就藏在image_list字段中,它是由列表形式构成,其中包含了组图的所有图片列表。如图所示。
图片列表信息
因此,只需将列表中的url字段提取出来。将每一组图都建立一个文件夹,文件夹名称就为组图的标题。接下来观察它的请求URL和Headers信息,可以看到这是一个GET请求,请求参数有offset、format、keyword、count、等。可以观察到offset为偏移量、控制数据分页。
Ajax请求
实战代码
#coding:utf-8
#author:zhouchuang
import requests
from urllib.parse import urlencode
from requests import codes
import os
from hashlib import md5
from multiprocessing.pool import Pool
import time
def get_page(offset):
params = {
'offset': offset, #根据offset确定页数
'format': 'json',
'keyword': '中秋', # 搜索内容
'autoload': 'true',
'count': '20',
'cur_tab': '1',
'from': 'search_tab'
}
base_url = 'https://www.toutiao.com/search_content/?'
url = base_url + urlencode(params) #最终需要的 url
try: #通用代码框架
resp = requests.get(url)
if codes.ok == resp.status_code:
return resp.json() #返回为json格式
except requests.ConnectionError:
return None
def get_images(json):
if json.get('data'):
data = json.get('data')
for item in data:
if item.get('cell_type') is not None: # 前提
continue
title = item.get('title')
images = item.get('image_list')
for image in images:
yield {
'image': 'https:' + image.get('url'), #打印最终的图片下载链接
'title': title
}
def save_image(item):
img_path = 'img' + os.path.sep + item.get('title') #os.path.sep 就是 / 路径分隔符
if not os.path.exists(img_path): #os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.makedirs(img_path) #os.makedirs() 方法用于递归创建目录。
try:
resp = requests.get(item.get('image')) #resp 为 图片url 地址
if codes.ok == resp.status_code:
file_path = img_path + os.path.sep + '{file_name}.{file_suffix}'.format( #文件路径为img/title/MD5值.jpg
file_name=md5(resp.content).hexdigest(), #MD5是一种加密算法,了解
file_suffix='jpg')
if not os.path.exists(file_path): #如果文件路径不存在
with open(file_path, 'wb') as f:
f.write(resp.content) #写所下载的文件路径
print('Downloaded image path is %s' % file_path)
else: #如果文件路径已经存在
print('Already Downloaded', file_path)
except requests.ConnectionError:
print('Failed to Save Image,item %s' % item)
def main(offset):
json = get_page(offset)
for item in get_images(json):
print(item)
save_image(item)
GROUP_START = 0
GROUP_END = 7 # 7页内容
if __name__ == '__main__':
pool = Pool() #多线程下载
groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)])
pool.map(main, groups) #将groups一个一个调出来传给main函数
pool.close()
pool.join()
time.sleep(1)
这样整个程序就完成了,运行之后就会发现图片都分文件夹保存下来了。
运行结果
保存结果
代码地址