500px并没有什么防爬虫的措施,爬取上面的图片还是相对简单的,唯一的问题是500px已被视觉中国收购,由于版权问题请谨慎使用爬取的图片
打开一个作者的主页面

直接从源码里得到的图片链接仅仅是缩略图,并不是高清图片

而且此处用了ajax动态加载,下拉到底部才会继续加载50张图片,所以想要直接从作者主页的源码爬取是比较困难的
查看网络

Ajax的功能是依赖xhr(XMLHttpRequest)来实现的,查看网络中获取的xhr响应内容,发现了一些json数据包,点击后可以看到包含了一些有关图片的具体信息。

新标签页打开后发现确实包含了许多图片的相关信息

可以看到共有7页,310个项目(图片),当前为第3页

再观察一下url,尝试修改url进行请求

去除掉其他品质的图片,只留下尺寸最大的图片,修改每页显示的图片为100,请求成功。

每页的图片数量达到了100,且只剩下最高品质图片的url
尝试修改每页显示200项

仍然只显示100项
看来不能一步到位
通过requests工具获取数据,不用请求头即可成功

获取到的a是一个dict对象

观察下图片的url的位置

即可获取所有图片的url
这里可以将一些有用的相关信息导入自建数据库以便进行筛选或管理,这里我们只需要图片的url用以下载
大致的思路就是这样,是脚本代码放在最后,写的比较粗糙,没考虑下载超时等之类问题
全部的脚本代码
import requests
import urllib.request
from multiprocessing import Pool
import os
import re
def get_id(url):
a = requests.get(url)
id = re.findall('"id":(.*?),', a.text)[0] #利用正则表达式解析响应获取作者的数字id
return id
def get_image(userid):
page="1"
images=[]
url="https://api.500px.com/v1/photos?feature=user&stream=photos&user_id="+userid+"&include_states=true&image_size[]=2048&page="+page+"&rpp=100" #对请求的url进行编辑
ifm=requests.get(url)
x=ifm.json()
dir=x['photos'][0]['user']['fullname'] #获取作者的名字用以新建目录
if not os.path.exists(dir):
os.mkdir(dir) #若没有这个目录则新建目录
for i in range(1,x['total_pages']+1): #获取页数并遍历
url="https://api.500px.com/v1/photos?feature=user&stream=photos&user_id="+userid+"&include_states=true&image_size[]=2048&page="+str(i)+"&rpp=100"
ifm = requests.get(url)
y = ifm.json()
for j in y['photos']:
image_m=(str(j['id']),j['name'],j['image_url'][0],dir) #获取部分需要的信息放在一个元组中
images.append(image_m) #将所有信息放在一个列表中
return images
def download_img(m):
try:
url=m[2] #图片url
path=m[3]+'/'+m[0]+'.jpg' #存放路径与图片名,为避免重名,用图片的id作为名字
if not os.path.exists(path): #若文件不存在则进行下载
# print(m[0],m[2])
urllib.request.urlretrieve(url,path)
except:
fail.append(m[0]) #对下载出错的图片id进行记录
if __name__=='__main__':
fail = []
userid=get_id("https://500px.com/vossiem") #输入作者的主页地址,获取作者数字id
a=get_image(userid) #输入作者数字id
print(len(a)) #照片总数
p=Pool(50) #新建进程池
for i in a:
p.apply_async(download_img,(i,))
p.close()
p.join()
print('failed:',fail)