写在前面

今天要抓取的网站为 https://500px.me/ ,这是一个摄影社区,在一个摄影社区里面本来应该爬取的是图片信息,可是我发现好像也没啥有意思的,忽然觉得爬取一下这个网站的摄影师更好玩一些,所以就有了这篇文章的由来。

基于上面的目的,我找了了一个不错的页面 https://500px.me/community/search/user

不过细细分析之后,发现这个页面并不能抓取到尽可能多的用户,因为下拉一段时间,就不能继续了,十分糟心,难道我止步于此了么,显然不可能的,一番的努力之后(大概废了1分钟吧),我找到了突破口,任意打开一个用户的个人中心页,就是点击上述链接的任意用户头像,出现如下操作。

用户个人中心页面,竟然有关注列表唉~~,nice啊,这个好趴啊,F12分析一下。

哒哒哒,数据得到了。

URL是 https://500px.me/community/res/relation/4f7fe110d4e0b8a1fae0632b2358c8898/follow?startTime=&page=1&size=10&type=json

参数分别如下,实际测试发现size可以设置为100

https://500px.me/community/res/relation/{用户ID}/follow?startTime=&page={页码}&size={每页数据}&type=json

那么我们只需要这么做就可以了

  1. 获取关注总数
  2. 关注总数除以100,循环得到所有的关注者(这个地方为什么用关注,不用粉丝,是因为被关注的人更加有价值)

    明确我们的目标之后,就可以开始写代码了。

撸代码

基本操作,获取网络请求,之后解析页面,取得关注总数。

用户的起始,我选择的id是5769e51a04209a9b9b6a8c1e656ff9566,你可以随机选择一个,只要他有关注名单,就可以。

导入模块,这篇博客,用到了redismongo,所以相关的基础知识,我建议你提前准备一下,否则看起来吃力。

import requests
import threading from redis import StrictRedis
import pymongo #########mongo部分#########################
DATABASE_IP = '127.0.0.1'
DATABASE_PORT = 27017
DATABASE_NAME = 'sun'
client = pymongo.MongoClient(DATABASE_IP,DATABASE_PORT)
db = client.sun
db.authenticate("dba", "dba")
collection = db.px500 # 准备插入数据 #########mongo部分######################### #########redis部分#########################
redis = StrictRedis(host="localhost",port=6379,db=1,decode_responses=True)
#########redis部分######################### #########全局参数部分#########################
START_URL = "https://500px.me/community/v2/user/indexInfo?queriedUserId={}" # 入口链接
COMMENT = "https://500px.me/community/res/relation/{}/follow?startTime=&page={}&size=100&type=json"
HEADERS = {
"Accept":"application/json",
"User-Agent":"你自己去找找可用的就行",
"X-Requested-With":"XMLHttpRequest"
} need_crawlids = [] # 待爬取的userid lock = threading.Lock() # 线程锁
#########全局参数部分#########################
def get_followee():
try:
res = requests.get(START_URL.format("5769e51a04209a9b9b6a8c1e656ff9566"),
headers=HEADERS,timeout=3)
data = res.json()
if data:
totle = int(data["data"]["userFolloweeCount"]) # 返回关注数
userid = data["data"]["id"] # 返回用户ID
return {
"userid":userid,
"totle":totle
} # 返回总数据
except Exception as e:
print("数据获取错误")
print(e)
if __name__ == '__main__':
start = get_followee() # 获取入口
need_crawlids.append(start)

上面代码中有一个非常重要的逻辑,就是为什么要先匹配种子地址的【关注数】和【用户ID】,这两个值是为了拼接下面的URL

https://500px.me/community/res/relation/{}/follow?startTime=&page={}&size=100&type=json

经过分析,你已经知道,这个地方第一个参数是用户id,第二个参数是页码page,page需要通过关注总数除以100得到。不会算的,好好在纸上写写吧~

我们可以通过一个方法,获取到了种子用户的关注列表,以此继续爬取下去,完善生产者代码。关键代码都进行了注释标注。

思路如下:

  1. 死循环不断获取need_crawlids 变量中的用户,然后获取该用户的关注者列表。
  2. 爬取到的信息,写入redis方便验证重复,快速存储。
class Product(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self._headers = HEADERS def get_follows(self,userid,totle):
try:
res = requests.get(COMMENT.format(userid,totle),headers=HEADERS,timeout=3)
data = res.json() if data:
for item in data:
yield {
"userid":item["id"],
"totle":item["userFolloweeCount"]
}
except Exception as e:
print("错误信息")
print(e)
self.get_follows(userid,totle) # 出错之后,重新调用 def run(self): while 1:
global need_crawlids # 调用全局等待爬取的内容 if lock.acquire():
if len(need_crawlids)==0: # 如果为0,无法进入循环
continue data = need_crawlids[0] # 取得第一个
del need_crawlids[0] # 使用完删除 lock.release() if data["totle"] == 0:
continue for page in range(1,data["totle"]//100+2):
for i in self.get_follows(data["userid"],page):
if lock.acquire():
need_crawlids.append(i) # 新获取到的,追加到等待爬取的列表里面
lock.release()
self.save_redis(i) # 存储到redis里面 def save_redis(self,data):
redis.setnx(data["userid"],data["totle"])
#print(data,"插入成功")

由于500px无反爬虫,所以运行起来速度也是飞快了,一会就爬取了大量的数据,目测大概40000多人,由于咱是写教程的,我停止了爬取。

这些数据不能就在redis里面趴着,我们要用它获取用户的所有信息,那么先找到用户信息接口,其实在上面已经使用了一次

https://500px.me/community/v2/user/indexInfo?queriedUserId={} 后面的queriedUserId对应的是用户id,只需要从刚才的数据里面获取redis的key就可以了,开始编写消费者代码吧,我开启了5个线程抓取。

class Consumer(threading.Thread):
def __init__(self):
threading.Thread.__init__(self) def run(self):
while 1:
key = redis.randomkey() # 随机获取一个key
if key:
# 删除获取到的key
redis.delete(key)
self.get_info(key) def get_info(self,key):
try:
res = requests.get(START_URL.format(key),headers=HEADERS,timeout=3)
data = res.json()
if data['status'] == "200":
collection.insert(data["data"]) # 插入到mongodb中
except Exception as e:
print(e)
return
if __name__ == '__main__':
start = get_followee() # 获取入口
need_crawlids.append(start) p = Product()
p.start() for i in range(1,5):
c = Consumer()
c.start()

代码没有特别需要注意的,可以说非常简单了,关于redis使用也不多。

redis.randomkey() # 随机获取一个key
redis.delete(key) # 删除key

(⊙o⊙)…经过几分钟的等待之后,大量的用户信息就来到了我的本地。

完整代码评论留言发送。

写在后面

emmmmmm...... 天天在CSDN写博客,明天就爬CSDN博客吧~~~

Python爬虫入门教程 16-100 500px摄影师社区抓取摄影师数据的更多相关文章

  1. Python爬虫入门教程 20-100 慕课网免费课程抓取

    写在前面 美好的一天又开始了,今天咱继续爬取IT在线教育类网站,慕课网,这个平台的数据量并不是很多,所以爬取起来还是比较简单的 准备爬取 打开我们要爬取的页面,寻找分页点和查看是否是异步加载的数据. ...

  2. Python爬虫入门教程 10-100 图虫网多线程爬取

    图虫网-写在前面 经历了一顿噼里啪啦的操作之后,终于我把博客写到了第10篇,后面,慢慢的会涉及到更多的爬虫模块,有人问scrapy 啥时候开始用,这个我预计要在30篇以后了吧,后面的套路依旧慢节奏的, ...

  3. Python爬虫入门教程 12-100 半次元COS图爬取

    半次元COS图爬取-写在前面 今天在浏览网站的时候,忽然一个莫名的链接指引着我跳转到了半次元网站 https://bcy.net/ 打开之后,发现也没有什么有意思的内容,职业的敏感让我瞬间联想到了 c ...

  4. Python爬虫入门教程: All IT eBooks多线程爬取

    All IT eBooks多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...

  5. Python爬虫入门教程: 半次元COS图爬取

    半次元COS图爬取-写在前面 今天在浏览网站的时候,忽然一个莫名的链接指引着我跳转到了半次元网站 https://bcy.net/ 打开之后,发现也没有什么有意思的内容,职业的敏感让我瞬间联想到了 c ...

  6. Python爬虫入门教程 14-100 All IT eBooks多线程爬取

    All IT eBooks多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...

  7. Python爬虫入门教程 11-100 行行网电子书多线程爬取

    行行网电子书多线程爬取-写在前面 最近想找几本电子书看看,就翻啊翻,然后呢,找到了一个 叫做 周读的网站 ,网站特别好,简单清爽,书籍很多,而且打开都是百度网盘可以直接下载,更新速度也还可以,于是乎, ...

  8. Python爬虫入门教程 26-100 知乎文章图片爬取器之二

    1. 知乎文章图片爬取器之二博客背景 昨天写了知乎文章图片爬取器的一部分代码,针对知乎问题的答案json进行了数据抓取,博客中出现了部分写死的内容,今天把那部分信息调整完毕,并且将图片下载完善到代码中 ...

  9. Python爬虫入门教程 25-100 知乎文章图片爬取器之一

    1. 知乎文章图片写在前面 今天开始尝试爬取一下知乎,看一下这个网站都有什么好玩的内容可以爬取到,可能断断续续会写几篇文章,今天首先爬取最简单的,单一文章的所有回答,爬取这个没有什么难度. 找到我们要 ...

随机推荐

  1. html网页调用本地exe程序

    1.使用记事本(或其他文本编辑器)创建一个protocal.reg文件,并写入以下内容 Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\ ...

  2. VS2013+ffmpeg开发环境搭建

    VS2013+ffmpeg开发环境搭建 转 https://blog.csdn.net/u014253332/article/details/86657868 一.准备ffmpeg相对应开发dll.i ...

  3. 【java】-- java反射机制

    参考文章:https://blog.csdn.net/sinat_38259539/article/details/71799078    https://blog.csdn.net/wanderlu ...

  4. elasticsearch简单操作

    现在,启动一个节点和kibana,接下来的一切操作都在kibana中Dev Tools下的Console里完成 创建一篇文档 将小黑的小姨妈的个人信息录入elasticsearch.我们只要输入 PU ...

  5. nodejs编译遇到的问题

    src\node_contextify.cc:631: Assertion 'args[1]->IsString()' failed. node 10 版本会出现这个问题, 安装natives后 ...

  6. 201771010126 王燕《面向对象设计 java》第十五周实验总结

    第一部分  理论部分 ◼ JAR文件◼ 应用程序首选项存储◼ Java Web Start JAR文件: 1.Java程序的打包:程序编译完成后,程序员将.class文件压缩打包为.jar文件后,GU ...

  7. [LeetCode] Binary Gap 二进制间隙

    Given a positive integer N, find and return the longest distance between two consecutive 1's in the ...

  8. jQuery-day01-介绍 和 选择器获取元素

    1 ,jQuery介绍 1.1,jquery的介绍,javascript库的关系.体验jquery.把js兼容性代码封装在jquery.js中,本身就是一个javascript库. 1.2,jQuer ...

  9. Centos7 通配符HTTPS证书申请 实测 笔记

    环境: 免费通配符HTTPS证书网址: https://letsencrypt.org/ 1.下载证书申请工具 [root@centos ~]# mkdir /opt/letsencrypt -p [ ...

  10. 实验5 Spark SQL编程初级实践

    今天做实验[Spark SQL 编程初级实践],虽然网上有答案,但都是用scala语言写的,于是我用java语言重写实现一下. 1 .Spark SQL 基本操作将下列 JSON 格式数据复制到 Li ...