今天用scrapy框架爬取一下所有知乎用户的信息。道理很简单,找一个知乎大V(就是粉丝和关注量都很多的那种),找到他的粉丝和他关注的人的信息,然后分别再找这些人的粉丝和关注的人的信息,层层递进,这样下来,只要有关注的人或者有粉丝的账号,几乎都能被爬下来。话不多说,进入正题。

1、首先按照上篇博客的介绍,先建立项目,然后建一个spider文件,scrapy  genspider  zhihu  www.zhihu.com.

进入settings.py,修改内容 ROBOTSTXT_OBEY = False,意思是知乎网页中禁止爬取的内容也可以爬的到。

再添加一个User_agent,因为知乎是通过浏览器识别的,否则知乎会禁止爬取

  1. DEFAULT_REQUEST_HEADERS = {
  2. 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  3. 'Accept-Language': 'en',
  4. 'User-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
  5. }

2、进入知乎网页页面,搜索一个大V,这里我用的是vczh,这个账号的关注量和粉丝都特别多。

  改写zhihu.py的内容如下:

  1. from scrapy import Request,Spider
  2.  
  3. class ZhihuSpider(Spider):
  4. name = 'zhihu'
  5. allowed_domains = ['www.zhihu.com']
  6. start_urls = ['http://www.zhihu.com/']
  7.  
  8. def start_requests(self): # zhihu.py 会先调用 start_requests 函数
  9. url = 'https://www.zhihu.com/api/v4/members/ji-he-61-7?include=allow_message%2Cis_followed%2Cis_following%2Cis_org%2Cis_blocking%2Cemployments%2Canswer_count%2Cfollower_count%2Carticles_count%2Cgender%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics'
  10. yield Request(url,callback=self.parse)
  11.  
  12. def parse(self, response):
  13. print(response.text)

随便找一个vczh关注的人,把他的Request URL拿过来请求一下,发现正常输出了结果,说明是能够获取 vczh 自己的信息的。

将URL换成 followees(vczh关注的人) 的Request URL,同样输出了正确的结果,说明 vczh 关注的人的信息也能正常输出。

经过观察发现,每个用户详细信息的 URL 只有 url_token 不同,因此分别构造 user_url 和 follows_url:

  1. class ZhihuSpider(Spider):
  2. name = 'zhihu'
  3. allowed_domains = ['www.zhihu.com']
  4. start_urls = ['http://www.zhihu.com/']
  5.  
  6. start_user = 'excited-vczh'
  7.  
  8. user_url = 'https://www.zhihu.com/api/v4/members/{user}?include={include}'
  9. user_query = 'allow_message,is_followed,is_following,is_org,is_blocking,employments,answer_count,follower_count,articles_count,gender,badge[?(type=best_answerer)].topics'
  10.  
  11. follows_url = 'https://www.zhihu.com/api/v4/members/{user}/followees?include={include}&offset={offset}&limit={limit}'
  12. follows_query = 'data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics'
  13.  
  14. def start_requests(self):
  15. yield Request(self.user_url.format(user=self.start_user, include=self.user_query),callback=self.parse_user)
  16. yield Request(self.follows_url.format(user=self.start_user, include=self.follows_query, offset=0, limit=20),callback=self.parse_follows)
  17.  
  18. def parse_user(self, response):
  19. result = json.loads(response.text)
  20. item = Zhihu3Item()
  21. for field in item.fields:
  22. if field in result.keys():
  23. item[field] = result.get(field)
  24. yield item
  25.  
  26. def parse_follows(self, response):
  27. results = json.loads(response.text)
  28. if 'data' in results.keys():
  29. for result in results.get('data'):
  30. yield Request(self.user_url.format(user=result.get('url_token'), include=self.user_query),
  31. self.parse_user)
  32.  
  33. if 'paging' in results.keys() and results.get('paging').get('is_end') == False: # 如果当前页不是最后一页
  34. next_page_str = results.get('paging').get('next')
  35. next_page = next_page_str.replace('https://www.zhihu.com/', 'https://www.zhihu.com/api/v4/')
  36. # next_page = next_page_str[0:22] + 'api/v4/' + next_page_str[22:len(next_page_str)] # 这种写法也行
  37. yield Request(next_page, self.parse_follows)

结果正确输出了 vczh 和 他所关注的用户的详细信息。

3、接下来,把 vczh 关注的用户 所 关注的用户的信息输出来:

在  def parse_user(self, response): 函数后添加一句

yield Request(self.follows_url.format(user=result.get('url_token'), include=self.follows_query, offset=0, limit=20),self.parse_follows) 就好了。

4、除了获取用户关注的人以外,还要获取用户的粉丝信息。经观察,发现粉丝信息的 URL 与关注的人的 URL 类似,改写以后的最终版本如下:

  1. class ZhihuSpider(Spider):
  2. name = 'zhihu'
  3. allowed_domains = ['www.zhihu.com']
  4. start_urls = ['http://www.zhihu.com/']
  5.  
  6. start_user = 'excited-vczh'
  7.  
  8. user_url = 'https://www.zhihu.com/api/v4/members/{user}?include={include}'
  9. user_query = 'allow_message,is_followed,is_following,is_org,is_blocking,employments,answer_count,follower_count,articles_count,gender,badge[?(type=best_answerer)].topics'
  10.  
  11. follows_url = 'https://www.zhihu.com/api/v4/members/{user}/followees?include={include}&offset={offset}&limit={limit}'
  12. follows_query = 'data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics'
  13.  
  14. followers_url = 'https://www.zhihu.com/api/v4/members/{user}/followers?include={include}&offset={offset}&limit={limit}'
  15. followers_query = 'data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics'
  16.  
  17. def start_requests(self):
  18. yield Request(self.user_url.format(user=self.start_user, include=self.user_query),callback=self.parse_user)
  19. yield Request(self.follows_url.format(user=self.start_user, include=self.follows_query, offset=0, limit=20),callback=self.parse_follows)
  20. yield Request(self.followers_url.format(user=self.start_user, include=self.followers_query, offset=0, limit=20),callback=self.parse_followers)
  21.  
  22. def parse_user(self, response):
  23. result = json.loads(response.text)
  24. item = Zhihu3Item()
  25. for field in item.fields:
  26. if field in result.keys():
  27. item[field] = result.get(field)
  28. yield item
  29.  
  30. yield Request(self.follows_url.format(user=result.get('url_token'), include=self.follows_query, offset=0, limit=20),self.parse_follows)
  31. yield Request(self.followers_url.format(user=result.get('url_token'), include=self.followers_query, offset=0, limit=20),self.parse_followers)
  32.  
  33. def parse_follows(self, response):
  34. results = json.loads(response.text)
  35. if 'data' in results.keys():
  36. for result in results.get('data'):
  37. yield Request(self.user_url.format(user=result.get('url_token'), include=self.user_query),
  38. self.parse_user)
  39.  
  40. if 'paging' in results.keys() and results.get('paging').get('is_end') == False: # 如果当前页不是最后一页
  41. next_page_str = results.get('paging').get('next')
  42. next_page = next_page_str.replace('https://www.zhihu.com/', 'https://www.zhihu.com/api/v4/')
  43. # next_page = next_page_str[0:22] + 'api/v4/' + next_page_str[22:len(next_page_str)] # 这种写法也行
  44. yield Request(next_page, self.parse_follows)
  45.  
  46. def parse_followers(self, response):
  47. results = json.loads(response.text)
  48. if 'data' in results.keys():
  49. for result in results.get('data'):
  50. yield Request(self.user_url.format(user=result.get('url_token'), include=self.user_query),
  51. self.parse_user)
  52.  
  53. if 'paging' in results.keys() and results.get('paging').get('is_end') == False: # 如果当前页不是最后一页
  54. next_page_str = results.get('paging').get('next')
  55. next_page = next_page_str.replace('https://www.zhihu.com/', 'https://www.zhihu.com/api/v4/')
  56. # next_page = next_page_str[0:22] + 'api/v4/' + next_page_str[22:len(next_page_str)] # 这种写法也行
  57. yield Request(next_page, self.parse_followers)

5、将输出的内容保存到MongoDb中

跟上一篇博文类似,在pipeline.py中写入一下内容,直接上代码:

  1. import pymongo
  2.  
  3. class MongoPipeline(object):
  4. def __init__(self, mongo_uri, mongo_db):
  5. self.mongo_uri = mongo_uri
  6. self.mongo_db = mongo_db
  7.  
  8. @classmethod
  9. def from_crawler(cls, crawler):
  10. return cls(
  11. mongo_uri=crawler.settings.get('MONGO_URI'),
  12. mongo_db=crawler.settings.get('MONGO_DB')
  13. )
  14.  
  15. def open_spider(self, spider):
  16. self.client = pymongo.MongoClient(self.mongo_uri)
  17. self.db = self.client[self.mongo_db]
  18.  
  19. def process_item(self, item, spider):
  20. self.db['information'].update({'url_token':item['url_token']},{'$set':item},True)
  21. return item # 根据'url_token'去重,True 表示如果重复就执行刷新操作,如果不重复就执行插入操作
  22.  
  23. def close_spider(self, spider):
  24. self.client.close()

在settings.py中写入以下代码:

  1. ITEM_PIPELINES = {
  2. 'zhihu_3.pipelines.MongoPipeline': 300
  3. }
  4. MONGO_URI='localhost'
  5. MONGO_DB = 'zhihu_3'

运行即可,成功保存到MongoDB中

Srapy 爬取知乎用户信息的更多相关文章

  1. 基于webmagic的爬虫小应用--爬取知乎用户信息

    听到“爬虫”,是不是第一时间想到Python/php ? 多少想玩爬虫的Java学习者就因为语言不通而止步.Java是真的不能做爬虫吗? 当然不是. 只不过python的3行代码能解决的问题,而Jav ...

  2. 利用 Scrapy 爬取知乎用户信息

    思路:通过获取知乎某个大V的关注列表和被关注列表,查看该大V和其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息. 一 ...

  3. 爬虫(十六):scrapy爬取知乎用户信息

    一:爬取思路 首先我们应该找到一个账号,这个账号被关注的人和关注的人都相对比较多的,就是下图中金字塔顶端的人,然后通过爬取这个账号的信息后,再爬取他关注的人和被关注的人的账号信息,然后爬取被关注人的账 ...

  4. 爬虫实战--利用Scrapy爬取知乎用户信息

    思路: 主要逻辑图:

  5. python3编写网络爬虫22-爬取知乎用户信息

    思路 选定起始人 选一个关注数或者粉丝数多的大V作为爬虫起始点 获取粉丝和关注列表 通过知乎接口获得该大V的粉丝列表和关注列表 获取列表用户信息 获取列表每个用户的详细信息 获取每个用户的粉丝和关注 ...

  6. [Python爬虫] Selenium爬取新浪微博客户端用户信息、热点话题及评论 (上)

    转载自:http://blog.csdn.net/eastmount/article/details/51231852 一. 文章介绍 源码下载地址:http://download.csdn.net/ ...

  7. 使用python scrapy爬取知乎提问信息

    前文介绍了python的scrapy爬虫框架和登录知乎的方法. 这里介绍如何爬取知乎的问题信息,并保存到mysql数据库中. 首先,看一下我要爬取哪些内容: 如下图所示,我要爬取一个问题的6个信息: ...

  8. 第二个爬虫之爬取知乎用户回答和文章并将所有内容保存到txt文件中

    自从这两天开始学爬虫,就一直想做个爬虫爬知乎.于是就开始动手了. 知乎用户动态采取的是动态加载的方式,也就是先加载一部分的动态,要一直滑道底才会加载另一部分的动态.要爬取全部的动态,就得先获取全部的u ...

  9. 【Python项目】爬取新浪微博个人用户信息页

    微博用户信息爬虫 项目链接:https://github.com/RealIvyWong/WeiboCrawler/tree/master/WeiboUserInfoCrawler 1 实现功能 这个 ...

随机推荐

  1. jchdl - RTL实例 - And2(结构体的使用)

    https://mp.weixin.qq.com/s/qTgeBF9N0mx5UK3xWDb3jg   jchdl对Verilog做了增强,增加了用户自定义结构体类型.使用自定义结构体,可以对输入和输 ...

  2. Java实现 LeetCode 477 汉明距离总和

    477. 汉明距离总和 两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量. 计算一个数组中,任意两个数之间汉明距离的总和. 示例: 输入: 4, 14, 2 输出: 6 解释: 在二进 ...

  3. Java实现 LeetCode 36 有效的数独

    36. 有效的数独 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在 ...

  4. 分布式ID总结

    分布式ID 生成的ID使用场景 几乎所有的业务系统,都有生成一个记录标识的需求,例如:message_id, order_id.这个记录标识往往就是数据库中的唯一主键,数据库上会建立聚集索引(clus ...

  5. 浅谈Python内置对象类型——数字篇(附py2和py3的区别之一)

    Python是一门面向对象的编程设计语言,程序中每一样东西都可以视为一个对象.Python内置对象可以分为简单类型和容器类型,简单类型主要是数值型数据,而容器类型是可以包含其他对象类型的集体,如序列. ...

  6. zabbix 中文乱码

    环境 zabbix 3.4.7 centos 7.4 问题现象 zabbix 中文乱码     解决方法 1.先准备一个字体包    Windows路径 C:\Windows\Fonts\simkai ...

  7. C# 反射与特性(十):EMIT 构建代码

    目录 构建代码 1,程序集(Assembly) 2,模块(Module) 3,类型(Type) 4,DynamicMethod 定义方法与添加 IL 前面,本系列一共写了 九 篇关于反射和特性相关的文 ...

  8. PHP 实现过滤参数字符的方法

    //参数处理函数2function RepPostVar2($val){ if($val!=addslashes($val)) { exit(); } if(substr($val,-1)==&quo ...

  9. @codechef - JADUGAR2@ Chef and Same Old Recurrence 2

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 定义 dp 序列: \[dp(1) = K\\ dp(n) = ...

  10. docker 容器命令

    语法docker run [OPTIONS] IMAGE [COMMAND] [ARG...] OPTIONS说明: -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/ST ...