首页 >后端开发 >Python教程 >如何写个爬虫程序扒下知乎某个回答所有点赞用户名单?

如何写个爬虫程序扒下知乎某个回答所有点赞用户名单?

WBOY
WBOY原创
2016-06-06 16:21:572555浏览

问一个人知乎账号想fo一下,结果她不告诉我,现在想想有点奇怪,有点好奇,好在我知道几个她点赞过的问题,想用社会工程学的方法筛选下,找出她的知乎账号。(匿了没法邀请,算了她应该不会来这个区)

回复内容:

每个回答的div里面都有一个叫 data-aid="12345678"的东西,
然后根据, www.zhihu.com/answer/12345678/voters_profile?&offset=10
这个json数据连接分析所有点赞的id和个人连接就行, 每10的点赞人数为一个json连接.

刚刚试了一下,需要登陆之后才能得到完整的数据, 登陆知乎可以参考我写的博客.
python模拟登陆知乎


比如我这个回答的data-aid = '22229844'
如何写个爬虫程序扒下知乎某个回答所有点赞用户名单?
<code class="language-python"><span class="c">#!/usr/bin/env python</span>
<span class="c"># -*- coding: utf-8 -*-</span>

<span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>

<span class="n">url</span> <span class="o">=</span> <span class="s">'http://www.zhihu.com'</span>
<span class="n">loginURL</span> <span class="o">=</span> <span class="s">'http://www.zhihu.com/login/email'</span>

<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">"User-Agent"</span><span class="p">:</span> <span class="s">'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:41.0) Gecko/20100101 Firefox/41.0'</span><span class="p">,</span>
    <span class="s">"Referer"</span><span class="p">:</span> <span class="s">"http://www.zhihu.com/"</span><span class="p">,</span>
    <span class="s">'Host'</span><span class="p">:</span> <span class="s">'www.zhihu.com'</span><span class="p">,</span>
<span class="p">}</span>

<span class="n">data</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'email'</span><span class="p">:</span> <span class="s">'</span>
<span class="n">xxxxx</span><span class="nd">@gmail.com</span><span class="s">',</span>
    <span class="s">'password'</span><span class="p">:</span> <span class="s">'</span>
<span class="n">xxxxxxx</span><span class="s">',</span>
    <span class="s">'rememberme'</span><span class="p">:</span> <span class="s">"true"</span><span class="p">,</span>
<span class="p">}</span>

<span class="n">s</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">session</span><span class="p">()</span>
<span class="c"># 如果成功登陆过,用保存的cookies登录</span>
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="s">'cookiefile'</span><span class="p">):</span>
    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'cookiefile'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">cookie</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
    <span class="n">s</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">cookie</span><span class="p">)</span>
    <span class="n">req1</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'zhihu.html'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">req1</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
<span class="c"># 第一次需要手动输入验证码登录</span>
<span class="k">else</span><span class="p">:</span>
    <span class="n">req</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
    <span class="k">print</span> <span class="n">req</span>

    <span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">req</span><span class="o">.</span><span class="n">text</span><span class="p">,</span> <span class="s">"html.parser"</span><span class="p">)</span>
    <span class="n">xsrf</span> <span class="o">=</span> <span class="n">soup</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">'input'</span><span class="p">,</span> <span class="p">{</span><span class="s">'name'</span><span class="p">:</span> <span class="s">'_xsrf'</span><span class="p">,</span> <span class="s">'type'</span><span class="p">:</span> <span class="s">'hidden'</span><span class="p">})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'value'</span><span class="p">)</span>

    <span class="n">data</span><span class="p">[</span><span class="s">'_xsrf'</span><span class="p">]</span> <span class="o">=</span> <span class="n">xsrf</span>

    <span class="n">timestamp</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>
    <span class="n">captchaURL</span> <span class="o">=</span> <span class="s">'http://www.zhihu.com/captcha.gif?='</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">timestamp</span><span class="p">)</span>
    <span class="k">print</span> <span class="n">captchaURL</span>

    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'zhihucaptcha.gif'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">captchaREQ</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">captchaURL</span><span class="p">)</span>
        <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">captchaREQ</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>
    <span class="n">loginCaptcha</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">'input captcha:</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
    <span class="n">data</span><span class="p">[</span><span class="s">'captcha'</span><span class="p">]</span> <span class="o">=</span> <span class="n">loginCaptcha</span>
    <span class="c"># print data</span>
    <span class="n">loginREQ</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">loginURL</span><span class="p">,</span>  <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
    <span class="c"># print loginREQ.url</span>
    <span class="c"># print s.cookies.get_dict()</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">loginREQ</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">'r'</span><span class="p">]:</span>
        <span class="c"># print loginREQ.json()</span>
        <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'cookiefile'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
            <span class="n">json</span><span class="o">.</span><span class="n">dump</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">get_dict</span><span class="p">(),</span> <span class="n">f</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">print</span> <span class="s">'login failed, try again!'</span>
        <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>

<span class="c"># 以http://www.zhihu.com/question/27621722/answer/48820436这个大神的399各赞为例子.</span>
<span class="n">zanBaseURL</span> <span class="o">=</span> <span class="s">'http://www.zhihu.com/answer/22229844/voters_profile?&offset={0}'</span>
<span class="n">page</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
    <span class="n">zanURL</span> <span class="o">=</span> <span class="n">zanBaseURL</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">page</span><span class="p">))</span>
    <span class="n">page</span> <span class="o">+=</span> <span class="mi">10</span>
    <span class="n">zanREQ</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">zanURL</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">)</span>
    <span class="n">zanData</span> <span class="o">=</span> <span class="n">zanREQ</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s">'payload'</span><span class="p">]</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">zanData</span><span class="p">:</span>
        <span class="k">break</span>
    <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">zanData</span><span class="p">:</span>
        <span class="c"># print item</span>
        <span class="n">zanSoup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="s">"html.parser"</span><span class="p">)</span>
        <span class="n">zanInfo</span> <span class="o">=</span> <span class="n">zanSoup</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">'a'</span><span class="p">,</span> <span class="p">{</span><span class="s">'target'</span><span class="p">:</span> <span class="s">"_blank"</span><span class="p">,</span> <span class="s">'class'</span><span class="p">:</span> <span class="s">'zg-link'</span><span class="p">})</span>
        <span class="k">if</span> <span class="n">zanInfo</span><span class="p">:</span>
            <span class="k">print</span> <span class="s">'nickname:'</span><span class="p">,</span> <span class="n">zanInfo</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'title'</span><span class="p">),</span>  <span class="s">'    '</span><span class="p">,</span>
            <span class="k">print</span> <span class="s">'person_url:'</span><span class="p">,</span> <span class="n">zanInfo</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'href'</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">anonymous</span> <span class="o">=</span> <span class="n">zanSoup</span><span class="o">.</span><span class="n">find</span><span class="p">(</span>
                <span class="s">'img'</span><span class="p">,</span> <span class="p">{</span><span class="s">'title'</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span> <span class="s">'class'</span><span class="p">:</span> <span class="s">"zm-item-img-avatar"</span><span class="p">})</span>
            <span class="k">print</span> <span class="s">'nickname:'</span><span class="p">,</span> <span class="n">anonymous</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'title'</span><span class="p">)</span>

        <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">print</span> <span class="n">count</span>
</code>
这里有个 Python 3 的项目 Zhihu-py3 7sDream/zhihu-py3 · GitHub

封装了知乎爬虫的各方面需求,比如获取用户信息,获取问题信息,获取答案信息,之类的……当然也包括点赞用户啥的,虽然是单线程同步式 但是平常用用还是可以滴。

这里是她的文档:Welcome to zhihu-py3’s documentation!

欢迎 Star 以及 Fork 或者贡献代码。

===

获取点赞用户灰常简单 大概就这样

<code class="language-python"><span class="kn">from</span> <span class="nn">zhihu</span> <span class="kn">import</span> <span class="n">ZhihuClient</span>

<span class="n">client</span> <span class="o">=</span> <span class="n">ZhihuClient</span><span class="p">(</span><span class="s">'cookies.json'</span><span class="p">)</span>

<span class="n">url</span> <span class="o">=</span> <span class="s">'http://www.zhihu.com/question/36338520/answer/67029821'</span>
<span class="n">answer</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">answer</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">'问题:{0}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">answer</span><span class="o">.</span><span class="n">question</span><span class="o">.</span><span class="n">title</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">'答主:{0}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">answer</span><span class="o">.</span><span class="n">author</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">'此答案共有{0}人点赞:</span><span class="se">\n</span><span class="s">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">answer</span><span class="o">.</span><span class="n">upvote_num</span><span class="p">))</span>

<span class="k">for</span> <span class="n">upvoter</span> <span class="ow">in</span> <span class="n">answer</span><span class="o">.</span><span class="n">upvoters</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="n">upvoter</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">upvoter</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
</code>
看到第一名的答案中的评论,补充一下如何发现aid这个关键特征的思路:

一句话概述:对人工操作时发送的HTTP Request/Response进行分析,找出关键定位特征。
工具:firebug

1. 点击 任意一个答案页面下面的超链接 等人赞同 发现会向类似于这样的
zhihu.com/answer/222298
URL发送数据。
从这个URL的格式上已经很容易猜到这就是给答案22229844 进行投票的投票者资料了,一看服务器返回的Response (一段JSON数据)也能说明这一点。那么只要我们可以向这个URL发送一段GET请求就能知道投票者了。剩下的就是要解决怎么找出这个URL的问题,也就是找到这个22229844 。
2. 既然知道当点击 等人赞同 会触发一段Ajax向这个URL发送请求,那这个22229844 要么在DOM中存储了,要么是计算出来的。既然如此,在DOM中搜索22229844这个字符串,很轻松就能找到这样的一个div:
<code class="language-cfm"><span class="nt"><div> <span class="na">data-copyable=</span><span class="s">"1"</span> <span class="na">data-isowner=</span><span class="s">"0"</span> <span class="na">data-helpful=</span><span class="s">"1"</span> <span class="na">data-deleted=</span><span class="s">"0"</span> <span class="na">data-created=</span><span class="s">"1444404675"</span> <span class="na">data-collapsed=</span><span class="s">"0"</span> <span class="na">data-atoken=</span><span class="s">"67029821"</span> <span class="na">data-author=</span><span class="s">"洛克"</span> <span class="na">data-qtoken=</span><span class="s">"36338520"</span> <span class="na">data-aid=</span><span class="s">"22229844"</span> <span class="na">itemtype=</span><span class="s">"http://schema.org/Answer"</span> <span class="na">itemscope=</span><span class="s">""</span> <span class="na">itemprop=</span><span class="s">"topAnswer"</span> <span class="na">class=</span><span class="s">"zm-item-answer"</span> <span class="na">tabindex=</span><span class="s">"-1"</span><span class="nt">></span>

我好奇的是,你说的社会工程学是啥?<br>据我所知,一般所谓社会工程学就是黑客的骗术,凭借已知信息骗取信任拿到自己要的信息,但是核心就是骗。<br>你现在是知道她点了哪个答案的赞,跟社会工程学有什么关系呢?<br>你是想说你知道她点过的多个答案,准备从同时赞过这些答案的人中找到她?<br>运气好可能一下子就找出来了,运气不好恐怕一堆候选人等着你。关键看你知道她赞过几个答案了。<br>论技术的话,我觉得用不着python写js在控制台跑就好了

找轮子哥 他有源码

轮子哥有爬取用户自动分析性别颜值值得关注程度的源码
</div></span></code>
声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn