1. 程式人生 > >python爬蟲——爬取知乎上自己關注的問題

python爬蟲——爬取知乎上自己關注的問題

與之前爬的網站圖片的不同的是,現在爬取的是要自己個人的關注的東西,所以需要做到模擬登入。模擬登入的原理是登入網站後,在瀏覽器上獲取儲存的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 七夕到了,給一個女生送什麼禮物好?

就不要吐槽我關注的問題和變數命名了,每個人的興趣都不一樣。既然你把問題爬下來了,然後關注者的資訊,只要你想要,就可以繼續爬,然後做資料分析。