利用Scrapy爬取所有知乎用户详细信息并存至MongoDB澳门新葡亰赌995577

澳门新葡亰赌995577 21

第三步、数据分析

澳门新葡亰赌995577 1

 

分析结果

  1. 平均用户日在线时长2小时

澳门新葡亰赌995577 2

 

从分布图上看大部分用户都在1小时以上,最猛的几个人超过8小时。

注:我这里统计的是每一局的存活时间,实际在线时长会比我这个更长。

  1. 女性角色被救次数高于男性

澳门新葡亰赌995577 3

 

终于知道为什么有那么多人妖了,原来在游戏里面可以占便宜啊。

  1. 女性角色救人次数高于男性

澳门新葡亰赌995577 4

 

给了大家一个带妹上分的好理由。

  1. 澳门新葡亰赌995577,周五大家最忙

澳门新葡亰赌995577 5

 

估计周五大家都要忙着交差和写周报了。

  1. 晚上22点是游戏高峰

澳门新葡亰赌995577 6

 

凌晨还有那么多人玩,你们不睡觉吗?

  1. 最远击杀距离639米

我看了一下98K、SKS 和 AWP 的有效射程,大致都在 800
米以内,所以这个值可信度还是可以的。
反过来看抖音上的那些超远距离击杀应该都是摆拍的。

  1. 能拿到「救死扶伤」称号才是最高荣耀

澳门新葡亰赌995577 7

 

从分布情况可以看出来,救死扶伤比十杀还要难。

澳门新葡亰赌995577 8

 

能拿到救死扶伤称号的大部分都是女性角色,再一次证明玩游戏要带妹。
回归到这个游戏的本质,那就是生存游戏,没什么比活下来更重要的了。

小结

通过以上的spider,我们实现了如上逻辑:

  • start_requests方法,实现了第一个大V用户的详细信息请求还有他的粉丝和关注列表请求。

  • parse_user方法,实现了详细信息的提取和粉丝关注列表的获取。

  • paese_follows,实现了通过关注列表重新请求用户并进行翻页的功能。

  • paese_followers,实现了通过粉丝列表重新请求用户并进行翻页的功能。

结尾

这次爬虫主要是利用了微信游戏频道可以查看陌生人数据的场景才能提取到这么多数据。我们可以通过同样的手段来分析王者荣耀和其它游戏的数据,有兴趣的同学可以尝试一下。

最后再说一下,Python学习交流群:125240963可以获取小编精心准备的海量Python学习资料

如果需要源码的话也可以在Python学习交流群:125240963获取

创建爬虫

接下来我们需要创建一个
spider,同样利用命令行,不过这次命令行需要进入到项目里运行。

cd zhihuuser
scrapy genspider zhihu www.zhihu.com

第二步、爬取数据

使用requests请求接口获取数据

澳门新葡亰赌995577 9

 

使用redis来标记已经爬取过的信息

澳门新葡亰赌995577 10

 

使用celery来管理队列

澳门新葡亰赌995577 11

 

然后在task中控制API请求和Redis数据实现完整的任务逻辑,如:

澳门新葡亰赌995577 12

 

开始抓取

澳门新葡亰赌995577 13

 

有入口之后我们就用celery来启动worker去开始爬虫

澳门新葡亰赌995577 14

 

通过flower,我们可以看到运行的效率还是非常不错的。

澳门新葡亰赌995577 15

 

本节分享一下爬取知乎用户所有用户信息的 Scrapy 爬虫实战。

背景

最近老板爱上了吃鸡(手游:全军出击),经常拉着我们开黑,只能放弃午休的时间,陪老板在沙漠里奔波。
上周在在微信游戏频道看战绩的时候突发奇想,是不是可以通过这个方式抓取到很多战斗数据,然后分析看看有什么规律。

首先,神枪镇楼

澳门新葡亰赌995577 16

 

更高效率

当然我们现在运行的是单机爬虫,只在一台电脑上运行速度是有限的,所以后面我们要想提高抓取效率,需要用到分布式爬虫,在这里需要用到
Redis 来维护一个公共的爬取队列。

更多的分布式爬虫的实现可以查看自己动手,丰衣足食!Python3网络爬虫实战案例

第一步、分析数据接口

使用Charles抓包

澳门新葡亰赌995577 17

 

https加密流量的处理

经过研究,可以通过在手机和电脑都安装Charles根证书的方式来实现对Https流量的分析

澳门新葡亰赌995577 18

 

数据接口

接下来就根据这些数据来找出我们需要的接口了,经过分析,主要涉及三个接口

  • 获取用户信息接口
  • 获取用户战绩列表接口
  • 获取用户指定战绩详细信息接口

下面我们一个一个看

  1. 获取用户信息接口

request

澳门新葡亰赌995577 19

 

response

澳门新葡亰赌995577 20

 

同理获取用户战绩列表接口和获取用户战绩详情接口

尝试最初的爬取

接下来我们什么代码也不修改,执行爬取,运行如下命令:

scrapy crawl zhihu

你会发现爬取结果会出现这样的一个错误:

500 Internal Server Error

访问知乎得到的状态码是500,这说明爬取并没有成功,其实这是因为我们没有加入请求头,知乎识别User-Agent发现不是浏览器,就返回错误的响应了。

所以接下来的一步我们需要加入请求 headers 信息,你可以在 Request
的参数里加,也可以在 spider
里面的custom_settings里面加,当然最简单的方法莫过于在全局 settings
里面加了。

我们打开settings.py文件,取消DEFAULT_REQUEST_HEADERS的注释,加入如下的内容:

DEFAULT_REQUEST_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
}

这个是为你的请求添加请求头,如果你没有设置 headers
的话,它就会使用这个请求头请求,添加了User-Agent信息,所以这样我们的爬虫就可以伪装浏览器了。

接下来重新运行爬虫。

scrapy crawl zhihu

这时你就会发现得到的返回状态码就正常了。

解决了这个问题,我们接下来就可以分析页面逻辑来正式实现爬虫了。

澳门新葡亰赌995577 21

MongoDB

非关系型数据库,项目开始之前请先安装好 MongoDB 并启动服务。

 

OAuth

它是Open Authorization的缩写。

OAUTH_token:OAUTH进行到最后一步得到的一个“令牌”,通过此“令牌”请求,就可以去拥有资源的网站抓取任意有权限可以被抓取的资源。

在这里我知乎并没有登陆,这里的OAuth值是

oauth c3cef7c66a1843f8b3a9e6a1e3160e20

经过我长久的观察,这个一直不会改变,所以可以长久使用,我们将它配置到DEFAULT_REQUEST_HEADERS里,这样它就变成了:

DEFAULT_REQUEST_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
    'authorization': 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20',
}

接下来如果我们重新运行爬虫,就可以发现可以正常爬取了。

欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~

Scrapy

Scrapy 是一个强大的爬虫框架,安装方式如下:

pip3 install scrapy

followers

上面我们实现了通过获取关注列表实现爬取循环,那这里少不了的还有粉丝列表,经过分析后发现粉丝列表的
api 也类似,只不过把 followee 换成了
follower,其他的完全相同,所以我们按照同样的逻辑添加 followers
相关信息,

最终spider代码如下:

# -*- coding: utf-8 -*-
import json

from scrapy import Spider, Request
from zhihuuser.items import UserItem


class ZhihuSpider(Spider):
    name = "zhihu"
    allowed_domains = ["www.zhihu.com"]
    user_url = 'https://www.zhihu.com/api/v4/members/{user}?include={include}'
    follows_url = 'https://www.zhihu.com/api/v4/members/{user}/followees?include={include}&offset={offset}&limit={limit}'
    followers_url = 'https://www.zhihu.com/api/v4/members/{user}/followers?include={include}&offset={offset}&limit={limit}'
    start_user = 'excited-vczh'
    user_query = 'locations,employments,gender,educations,business,voteup_count,thanked_Count,follower_count,following_count,cover_url,following_topic_count,following_question_count,following_favlists_count,following_columns_count,answer_count,articles_count,pins_count,question_count,commercial_question_count,favorite_count,favorited_count,logs_count,marked_answers_count,marked_answers_text,message_thread_token,account_status,is_active,is_force_renamed,is_bind_sina,sina_weibo_url,sina_weibo_name,show_sina_weibo,is_blocking,is_blocked,is_following,is_followed,mutual_followees_count,vote_to_count,vote_from_count,thank_to_count,thank_from_count,thanked_count,description,hosted_live_count,participated_live_count,allow_message,industry_category,org_name,org_homepage,badge[?(type=best_answerer)].topics'
    follows_query = 'data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics'
    followers_query = 'data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics'

    def start_requests(self):
        yield Request(self.user_url.format(user=self.start_user, include=self.user_query), self.parse_user)
        yield Request(self.follows_url.format(user=self.start_user, include=self.follows_query, limit=20, offset=0),
                      self.parse_follows)
        yield Request(self.followers_url.format(user=self.start_user, include=self.followers_query, limit=20, offset=0),
                      self.parse_followers)

    def parse_user(self, response):
        result = json.loads(response.text)
        item = UserItem()

        for field in item.fields:
            if field in result.keys():
                item[field] = result.get(field)
        yield item

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

        yield Request(
            self.followers_url.format(user=result.get('url_token'), include=self.followers_query, limit=20, offset=0),
            self.parse_followers)

    def parse_follows(self, response):
        results = json.loads(response.text)

        if 'data' in results.keys():
            for result in results.get('data'):
                yield Request(self.user_url.format(user=result.get('url_token'), include=self.user_query),
                              self.parse_user)

        if 'paging' in results.keys() and results.get('paging').get('is_end') == False:
            next_page = results.get('paging').get('next')
            yield Request(next_page,
                          self.parse_follows)

    def parse_followers(self, response):
        results = json.loads(response.text)

        if 'data' in results.keys():
            for result in results.get('data'):
                yield Request(self.user_url.format(user=result.get('url_token'), include=self.user_query),
                              self.parse_user)

        if 'paging' in results.keys() and results.get('paging').get('is_end') == False:
            next_page = results.get('paging').get('next')
            yield Request(next_page,
                          self.parse_followers)

需要改变的位置有

  • start_requests里面添加yield followers信息

  • parse_user里面里面添加yield followers信息

  • parse_followers做相应的的抓取详情请求和翻页

如此一来,spider
就完成了,这样我们就可以实现通过社交网络递归的爬取,把用户详情都爬下来。

环境需求

思路分析

我们都知道每个人都有关注列表和粉丝列表,尤其对于大V来说,粉丝和关注尤其更多。

如果我们从一个大V开始,首先可以获取他的个人信息,然后我们获取他的粉丝列表和关注列表,然后遍历列表中的每一个用户,进一步抓取每一个用户的信息还有他们各自的粉丝列表和关注列表,然后再进一步遍历获取到的列表中的每一个用户,进一步抓取他们的信息和关注粉丝列表,循环往复,不断递归,这样就可以做到一爬百,百爬万,万爬百万,通过社交关系自然形成了一个爬取网,这样就可以爬到所有的用户信息了。当然零粉丝零关注的用户就忽略他们吧~

爬取的信息怎样来获得呢?不用担心,通过分析知乎的请求就可以得到相关接口,通过请求接口就可以拿到用户详细信息和粉丝、关注列表了。

接下来我们开始实战爬取。