输入搜索词 「 世界杯」回车之后,打开调试工具,找到请求,并分析其源代码,发现找不到我们所要的内容,例如图片上的「当端午遇上世界杯」 在网页源代码上并没有找到,由此,这些数据应该是通过 ajax 方式传递的,打开调试工具的 XHR 发现果然有请求的数据,查看其 preview 可以看到是一系列 json 格式的数据,分析这些 json 数据,我们发现我们需要的数据,如图片地址,图片标题。。。都可以从这里面取到。

分析完之后,就开始写代码爬取了
首先爬取网站内容,获取其中 ajax 的 json 数据,这里通过python 的 urllib 库的urlencode()来将 json 格式的参数自动解析为url的字符串形式。

例如当page=1 时 会解析成这个样子,就可以获得ajax请求的完整数据的 url :

http://www.shijue.me/community/search?size=20&orderby=rating&key=%E4%B8%96%E7%95%8C%E6%9D%AF&type=json&page=1&license=-1 
 def get_content(page): 
 parameters = { 
 ‘key’:’世界杯’, 
 ‘type’:’json’, 
 ‘page’:page, 
 ‘size’:’20’, 
 ‘license’:-1, 
 ‘orderby’:’rating’, 
 } 
 # size:每一页有size组图 
 # orderby: 通过rating(等级)排序 
 # 用urlencode() 方法构造请求的GET参数,然后用requests请求这个链接,如果返回状态码为200,则调用response的json格式返回 
 url = ‘http://www.shijue.me/community/search?’ + urlencode(parameters) 
 try: 
 response = requests.get(url) 
 if response.status_code == 200: 
 return response.json() 
 except requests.ConnectionError: 
 return None 
 获取上面的 json 数据后,将 json 数据解析出来,获取其中的 title 和 image 的url地址,并将其保存到本地。同时由于网页的 MD5 加密方式,同时获取其 MD5 值可以保证下载的名称的唯一性。 def get_images(json): 
 if json.get(‘dataArray’): 
 for item in json.get(‘dataArray’): 
 title = item.get(‘title’) 
 image =item.get(‘url’) 
 yield { 
 ‘image’:image, 
 ‘title’:title 
 } 
 ”’ 
 实现一个保存图片的方法 save_image(), 其中item就是前面返回的一个字典,根据item的title创建文件夹,然后请求这个图片的二进制数据, 
 以二进制的形式写入文件,图片的名称可以使用其内容的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(‘已经下载’, file_path) 
 except requests.ConnectionError: 
 print(‘保存图片失败’) 
 运行之后,可以看到本地文件中就有了这么多下载好的结果了。改进一下,将数据存储到 mongodb 数据库中去.。
mongodb 是一个适合进行文档存储的非关系型数据库,所有这里将图片信息通过 mongodb 存储.
设置 Mongodb 配置信息
client = MongoClient() 
 db = client[‘picture’] 
 collection = db[‘picture’] 
 max_page = 10 
 存入mongodb 中,我们可以存储多一点信息,例如图片的作者,创作时间,主题。。。。暂时根据需求为了方便就只获取这么多信息,图片的 url 地址当然不能少。由此改写一下获取的数据。def get_monmgodb(json): 
 # 解析json数据 并获取 author,createDate,title, image 作为存入 mongodb的结果集 
 if json.get(‘dataArray’): 
 # 循环获取图片相关信息 
 for item in json.get(‘dataArray’): 
 author = item.get(‘uploaderName’) 
 title = item.get(‘title’) 
 image = item.get(‘url’) 
 createDate = item.get(‘createDate’) 
 # 将结果构造成一个字典形式并返回一个生成器 
 yield { 
 ‘author’:author, 
 ‘title’:title, 
 ‘image’:image, 
 ‘createDate’:createDate 
 } 
 最后用过 insert()将获得的字典形式的数据存入数据库就完成了,如有需要直接从数据库中取出需要的数据进行下载,以免都存在硬盘中占用资源.def save_mongdb(result): 
 collection.insert(result) 
 print(” 保存到mongodb成功 “) 
 运行之后,打开mongodb客户端,可以看到所有数据已经存到数据库里了。以上就是通过分析 ajax 爬取网页的过程,如有不足或疏漏,欢迎指教。
import requests 
 import os 
 from multiprocessing import Pool 
 from hashlib import md5 
 from urllib.parse import urlencodefrom pymongo import MongoClient
”’ 
 作者:starichat 
 时间:2018.7.13 
 内容: 分析视觉中国设计师社区网站,利用ajax爬取结果 
 ”’爬取网站内容,获取 ajax 的 json 数据
client = MongoClient() 
 db = client[‘picture’] 
 collection = db[‘picture’] 
 max_page = 10def get_content(page): 
 parameters = { 
 ‘key’:’世界杯’, 
 ‘type’:’json’, 
 ‘page’:page, 
 ‘size’:’20’, 
 ‘license’:-1, 
 ‘orderby’:’rating’, 
 }# 用urlencode() 方法构造请求的GET参数,然后用requests请求这个链接,如果返回状态码为200,则调用response的json格式返回
url = 'http://www.shijue.me/community/search?' + urlencode(parameters)
print(url)
try:
    response = requests.get(url)
    if response.status_code == 200:
        return response.json()
except requests.ConnectionError:
    return None”’ 
 实现一个保存图片的方法 save_image(), 其中item就是前面返回的一个字典,根据item的title创建文件夹,然后请求这个图片的二进制数据, 
 以二进制的形式写入文件,图片的名称可以使用其内容的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.ConnectionError: 
 print(‘Failed to save Image’)def get_monmgodb(json): 
 # 解析json数据 并获取 author,createDate,title, image 作为存入 mongodb的结果集 
 if json.get(‘dataArray’): 
 # 循环获取图片相关信息 
 for item in json.get(‘dataArray’): 
 author = item.get(‘uploaderName’) 
 title = item.get(‘title’) 
 image = item.get(‘url’) 
 createDate = item.get(‘createDate’) 
 # 将结果构造成一个字典形式并返回一个生成器 
 yield { 
 ‘author’:author, 
 ‘title’:title, 
 ‘image’:image, 
 ‘createDate’:createDate 
 } 
 def save_mongdb(result): 
 collection.insert(result) 
 print(” 保存到mongodb成功 “)def main(page): 
 json = get_content(page) 
 print(json) 
 for result in get_monmgodb(json): 
 try : 
 save_mongdb(result) 
 save_image(result) 
 except : 
 pass 
 continue 
 GROUP_START = 1 
 GROUP_END = 2 # 暂时以爬取 20 页为例 
 if name == ‘main‘: 
 pool = Pool() 
 groups = ([x * 2for x in range(GROUP_START,GROUP_END + 1)]) 
 pool.map(main,groups) 
 pool.close() 
 pool.join()