python爬虫——爬取知乎上自己关注的问题

标签: 爬虫python知乎爬取知乎
5549人阅读 评论(0) 收藏 举报
分类:

与之前爬的网站图片的不同的是,现在爬取的是要自己个人的关注的东西,所以需要做到模拟登录。模拟登录的原理是登录网站后,在浏览器上获取保存的cookies信息,填充之后与请求一起发送。


如果前面的爬取图片的会爬取了,对于这个解析字符串的也没有多大问题了。


一直看着知乎上很多程序员把自己关注的人的答案爬下来之后整理来看,那个时候开始又开始对爬虫这个东西特别感兴趣,对一个妹纸在美国搭了搭了个环境,爬了Twitter后进行数据分析的行为更是佩服,对方是个妹纸,但不是程序员,嗯,她自己还说代码写得丑,用代码写,有空再用java写多一次爬虫。


后面就真的自己动手写了,从简单地看别人如何模拟登录,到自己爬出自己关注的所有问题。


简单来说还是和前面写得爬图片网站一样,下滑时有请求,不过这个请求对headers还是cookies有限制,就需要自己动手尝试了。数据传输对了之后就是对json串的解析。然后获取自己所需要的东西。



#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: Administrator
# @Date:   2015-10-31 15:45:27
# @Last Modified by:   Administrator
# @Last Modified time: 2015-11-23 16:57:31
import requests
import sys
import json
import re
reload(sys)
sys.setdefaultencoding('utf-8')


#获取到匹配字符的字符串
def find(pattern,test):
    finder = re.search(pattern, test)
    start = finder.start()
    end = finder.end()
    return test[start:end-1]


cookies = {
    '_ga':'GA1.2.10sdfsdfsdf', '_za':'8d570b05-b0b1-4c96-a441-faddff34',
    'q_c1':'23ddd234234',
    '_xsrf':'234id':'"ZTE3NWY2ZTsdfsdfsdfWM2YzYxZmE=|1446435757|15fef3b84e044c122ee0fe8959e606827d333134"',
    'z_c0':'"QUFBQXhWNGZsdfsdRvWGxaeVRDMDRRVDJmSzJFN1JLVUJUT1VYaEtZYS13PT0=|14464e234767|57db366f67cc107a05f1dc8237af24b865573cbe5"',
    '__utmt':'1', '__utma':'51854390.109883802f8.1417518721.1447917637.144c7922009.4',
    '__utmb':'518542340.4.10.1447922009', '__utmc':'51123390', '__utmz':'5185435454sdf06.1.1.utmcsr=zhihu.com|utmcgcn=(referral)|utmcmd=referral|utmcct=/',
    '__utmv':'51854340.1d200-1|2=registration_date=2028=1^3=entry_date=201330318=1'}

headers = {'user-agent': 
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36',
            'referer':'http://www.zhihu.com/question/following',
            'host':'www.zhihu.com','Origin':'http://www.zhihu.com',
            'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
            'Connection':'keep-alive','X-Requested-With':'XMLHttpRequest','Content-Length':'81',
            'Accept-Encoding':'gzip,deflate','Accept-Language':'zh-CN,zh;q=0.8','Connection':'keep-alive'
            }

#多次访问之后,其实一加载时加载20个问题,具体参数传输就是offset,以20递增

dicc = {"offset":60}
n=20
b=0

# 与爬取图片相同的是,往下拉的时候也会发送http请求返回json数据,但是不同的是,像模拟登录首页不同的是除了
# 发送form表单的那些东西后,知乎是拒绝了我的请求了,刚开始以为是headers上的拦截,往headers添加浏览器
# 访问是的headers那些信息添加上,发现还是拒绝访问。

#想了一下,应该是cookie原因。这个加载的请求和模拟登录首页不同
#所以补上其他的cookies信息,再次请求,请求成功。
for x in xrange(20,460,20):
    n = n+20
    b = b+20
    dicc['offset'] = x
    formdata = {'method':'next','params':'{"offset":20}','_xsrf':'20770d88051f0f45e941570645f5e2e6'}

    #传输需要json串,和python的字典是有区别的,需要转换
    formdata['params'] = json.dumps(dicc)
    # print json.dumps(dicc)
    # print dicc



    circle = requests.post("http://www.zhihu.com/node/ProfileFollowedQuestionsV2",
                            cookies=cookies,data=formdata,headers=headers)

    #response内容 其实爬过一次之后就大同小异了。 都是
    #问题返回的json串格式
    # {"r":0,
    #  "msg": ["<div class=\"zm-profile-section-item zg-clear\">\n
    #  <span class=\"zm-profile-vote-count\">\n<div class=\"zm-profile-vote-num\">205K<\/div>\n
    #  <div class=\"zm-profile-vote-type\">\u6d4f\u89c8<\/div>\n
    #  <\/span>\n<div class=\"zm-profile-section-main\">\n
    #  <h2 class=\"zm-profile-question\">\n
    #  <a class=\"question_link\" target=\"_blank\" href=\"\/question\/21719532\">
    #  \u4ec0\u4e48\u4fc3\u4f7f\u4f60\u8d70\u4e0a\u72ec\u7acb\u5f00\u53d1\u8005\u4e4b\u8def\uff1f<\/a>\n
    #  <\/h2>\n<div class=\"meta zg-gray\">\n<a data-follow=\"q:link\" class=\"follow-link zg-unfollow meta-item\" 
    #  href=\"javascript:;\" id=\"sfb-868760\">
    #  <i class=\"z-icon-follow\"><\/i>\u53d6\u6d88\u5173\u6ce8<\/a>\n<span class=\"zg-bull\">•<\/span>\n63 \u4e2a\u56de\u7b54\n<span class=\"zg-bull\">•<\/span>\n3589 \u4eba\u5173\u6ce8\n<\/div>\n<\/div>\n<\/div>",
    # "<div class=\"zm-profile-section-item zg-clear\">\n
    # <span class=\"zm-profile-vote-count\">\n
    # <div class=\"zm-profile-vote-num\">157K<\/div>\n
    # <div class=\"zm-profile-vote-type\">\u6d4f\u89c8<\/div>\n
    # <\/span>\n<div class=\"zm-profile-section-main\">\n
    # <h2 class=\"zm-profile-question\">\n
    # <a class=\"question_link\" target=\"_blank\" href=\"\/question\/31764065\">
    # \u672c\u79d1\u6e23\u6821\u7684\u5b66\u751f\u5982\u4f55\u8fdb\u5165\u7f8e\u5e1d\u725b\u6821\u8bfbPhD\uff1f<\/a>\n
    # <\/h2>\n<div class=\"meta zg-gray\">\n
    # <a data-follow=\"q:link\" class=\"follow-link zg-unfollow meta-item\" href=\"javascript:;\" id=\"sfb-4904877\">
    # <i class=\"z-icon-follow\"><\/i>\u53d6\u6d88\u5173\u6ce8<\/a>\n<span class=\"zg-bull\">•
    # <\/span>\n112 \u4e2a\u56de\u7b54\n<span class=\"zg-bull\">•<\/span>\n1582 \u4eba\u5173\u6ce8\n
    # <\/div>\n<\/div>\n<\/div>"]}  
    # print circle.content

    #同样json串需要自己 转换成字典后使用
    jsondict = json.loads(circle.text)
    msgstr = jsondict['msg']
    # print len(msgstr)

    #根据自己所需要的提取信息规则写出正则表达式
    pattern = 'question\/.*?/a>'
    try:
        for y in xrange(0,20):
            wholequestion = find(pattern, msgstr[y])
            pattern2 = '>.*?<'
            finalquestion = find(pattern2, wholequestion).replace('>','')
            print str(b+y)+" "+finalquestion
            
    #当问题已经访问完后再传参数 抛出异常 此时退出循环
    except Exception, e:
        print "全部%s个问题" %(b+y)
        break


最后:

307 类似「手指月亮耳朵会缺」之类的话语是怎么流传下来的?
308 哪个瞬间发觉自己真的很穷?
309 活在过去、活在当下和活在未来这三种心态有何区别,对生活又有什么启示?
310 如何让妈妈不感到孤独?
311 游戏与成长有必然的联系吗,有没有必要戒掉游戏?
312 财务自由的感觉是怎样的?
313 阿里的市值为什么比腾讯高那么多?
314 不如自己的人毕业之后工资远高于自己,我应该怎样调整心态?
315 在小县城里,程序员和公务员两种职业有何不同?
316 七夕到了,给一个女生送什么礼物好?


就不要吐槽我关注的问题和变量命名了,每个人的兴趣都不一样。既然你把问题爬下来了,然后关注者的信息,只要你想要,就可以继续爬,然后做数据分析。

7
1

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1031600次
    • 积分:8917
    • 等级:
    • 排名:第2117名
    • 原创:131篇
    • 转载:7篇
    • 译文:9篇
    • 评论:494条
    博客专栏
    My GitHub