python 爬取视觉中国网站

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zzlong2288/article/details/81037606

python 爬取视觉中国设计师社团网站
阅读本文需要 5 分钟

如今版权越来越重要了,特别是今年。前几天,在一个的圈子里看到一条消息,有公司专门针对一些图片对不知情使用者索赔,说一句请各位使用图片的时候明确是否侵权。

借此来学习一下 python 如何用 100 行代码爬取视觉中国网站的设计图片并批量下载,今天我们就开始试着爬取一下视觉中国的网站里的图片,所有图片仅做学习,不做商用。

先分析一下网页

输入搜索词 「 世界杯」回车之后,打开调试工具,找到请求,并分析其源代码,发现找不到我们所要的内容,例如图片上的「当端午遇上世界杯」 在网页源代码上并没有找到,由此,这些数据应该是通过 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 urlencode

from pymongo import MongoClient

”’
作者:starichat
时间:2018.7.13
内容: 分析视觉中国设计师社区网站,利用ajax爬取结果
”’

爬取网站内容,获取 ajax 的 json 数据

client = MongoClient()
db = client[‘picture’]
collection = db[‘picture’]
max_page = 10

def 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()
所有代码以上传至 github 上了,如有需要,可以点击阅读原文查看。

如觉得有用,欢迎转发及留言。

还是友情提醒下:文章使用图片时使用请注意下版权。

关注有惊喜。收货不只是一点点喔!
公众号:
starichat

展开阅读全文

没有更多推荐了,返回首页