python-新浪爬取話題微博實踐

說完模擬登錄之后呢,現(xiàn)在講述對于手機端新浪的爬取過程,此例講述針對Ajax異步請求內容的爬取,以新浪微博“小黃車”話題下的微博為例

分析過程####

1.爬取入口頁面:http://m.weibo.cn/k/%E5%B0%8F%E9%BB%84%E8%BD%A6?from=feed

2.微博信息所在位置查找
當你進入該話題時,通過查看源代碼發(fā)現(xiàn)里面并沒有頁面上的微博信息,那么這些信息在哪呢?是怎么載入到頁面的呢?打開開發(fā)者工具,當你鼠標滑到頁面底端時繼續(xù)滑動會加載出新的頁面,這個時候會發(fā)現(xiàn)網(wǎng)絡中的XHR請求會對應增加一項,并且查看響應會發(fā)現(xiàn)里面包含了頁面的各種信息。主題微博信息第一頁在cards的第五個對象下的cardgroup中,其余頁面均在cards的第一個對象下的cardgroup中如下圖

Paste_Image.png
Paste_Image.png

發(fā)現(xiàn)頁面內容所在之后就需要構造類似的請求,以得到包含微博信息的響應json文件。
3.請求規(guī)律
那么,又一個問題來了,請求有什么規(guī)律呢?請求可在標題頭中查看,具體可點擊編輯和重發(fā)查看具體信息,具體參數(shù)可在參數(shù)中查看

Paste_Image.png

加載新一頁之后發(fā)現(xiàn)這些請求除了since_id這項參數(shù)是不一樣的之外,其余都是一樣的,也就是說話題下的微博分頁是根據(jù)since_id來確定的,每當頁面滑倒底部時,繼續(xù)往下滑則會發(fā)送新的請求,請求中的since_id標志上一頁加載到哪一條微博,現(xiàn)在應該從哪一條微博開始展示。這樣就實現(xiàn)了分頁,因此,接下來就是找到since_id的內容來源于哪里就可以開始構造請求了,經查看后發(fā)現(xiàn)每一個請求的since_id內容都可以在前一項請求中的響應中找到

Paste_Image.png

代碼講解####

1.思路介紹
首先構造請求,第一頁是沒有since_id參數(shù)的,所以除since_id外的請求參數(shù)可固定,since_id則通過每一次讀取響應內容中的since_id動態(tài)替換,然后成功讀取響應內容后(響應內容為json)用python內置json庫載入后,最后就可以方便提取想要的內容了。
2.源代碼
# -- coding: utf-8 --
import urllib
import urllib2
from bs4 import BeautifulSoup
import re
import os
import xlwt
import xlrd
from xlutils.copy import copy

import time
import string
import datetime
import sys
import shutil
import codecs

import traceback
import json

class WeiboContent:
    '''
    output:
    info_list = [(time, user_name, source, user_statuses_count, user_followers_count, user_follow_count, 
    user_verified, user_verified_type, user_urank, location, content, urls, pic_num, audios, mention)]
    '''
    def readHtml(self):
        try:
            info_list = []
            user_agent = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0'
            cookies = '"_T_WM=...."' #這里的cookie直接從瀏覽器中粘過來了,具體可參考上一篇文章
            headers = { 'User-Agent' : user_agent , 'cookie': cookies}
            page = 1 
           #構造固定的一些參數(shù)
            form_data = {
                'extparam' : '小黃車',
                'from' : 'feed',
                'luicode' : '10000011',
                'lfid' : '100808b0a0455a95cc4937460d29aa3076aec4',
                'containerid' : '100808topic'

            }
            since_id = ''
            #這里是以since_id為循環(huán)終止條件,最后一頁沒有since_id,所以當獲取出錯時跳出循環(huán)
            while page:                
                if page > 1:
                    form_data['since_id'] = since_id
                    form_data['containerid'] = containerid
                #將form_data的鍵值對轉換為以連接符&劃分的字符串
                formData = urllib.urlencode(form_data)
                url = 'http://m.weibo.cn/api/container/getIndex?'
                #構造request請求
                request = urllib2.Request(url = url, headers = headers, data = formData)
                index_doc = urllib2.urlopen(request).read()
                #使用json.loads()將獲取的返回內容轉換成json格式
                index_json = json.loads(index_doc)
                try:
                    since_id = index_json['pageInfo']['since_id']
                except:
                    traceback.print_exc()
                    print 'end get data,since-id wrong'
                    break                    
                if page == 1:
                    card_group = index_json['cards'][5]['card_group']
                else:
                    card_group = index_json['cards'][0]['card_group']
                #遍歷提取card_group中每一條微博的信息
                for card in card_group:
                    try:
                        mblog = card['mblog']
                        #針對時間中的分鐘前和今天做標準化時間處理
                        time = mblog['created_at']
                        if len(re.findall('分鐘前'.decode('utf-8'), time)) == 1:
                            num = int(time.split('分鐘前'.decode('utf-8'))[0])
                            time = datetime.datetime.now() - datetime.timedelta(minutes = num)
                            time = time.strftime('%m-%d %H:%m')
                        
                        if len(re.findall('今天'.decode('utf-8'), time)) == 1: 
                            hour = time.split('今天'.decode('utf-8'))[1]
                            time = '04-19' + hour #這里寫的比較隨意,直接給出日期,可利用和時間有關函數(shù)動態(tài)獲取爬取當天的日期
                        #獲取微博內容,如果為長微博需獲取全文的鏈接地址進一步獲取微博全部內容
                        isLongText = mblog['isLongText']
                        text = mblog['text']
                        if isLongText:
                            text_id = mblog['id']
                            text_%text_id
                            text_req = urllib2.Request(url = text_href, headers = headers)
                            text_doc = urllib2.urlopen(text_req).read()
                            text_json = json.loads(text_doc)
                            text = text_json['longTextContent']
                        #提取微博內容的一些特征信息
                        text_soup = BeautifulSoup(text,"html.parser")
                        content = text_soup.get_text()
                        urls = len(re.findall('small_web_default.png', text)) + len(re.findall('small_article_default.png', text))
                        audios = len(re.findall('small_video_default.png', text)) 
                        mention =  len(re.findall('<a.href.*?@.*?</a>', text))
                        topic = len(re.findall('<a.*?href.*?#.*?#</a>', text))
                      
                        source = mblog['source']
                        reposts_count = mblog['reposts_count']
                        comments_count = mblog['comments_count']
                        attitudes_count = mblog['attitudes_count']
                        #提取用戶信息
                        user = mblog['user']
                        user_id = user['id']
                        user_gender = user['gender']
                        user_statuses_count = user['statuses_count'] #微博數(shù)
                        user_followers_count = user['followers_count'] #粉絲數(shù)
                        user_follow_count = user['follow_count'] #關注數(shù)
                        user_verified = user['verified']
                        #verified_type:-1普通用戶 0名人 1政府 2企業(yè) 3媒體 4校園 5網(wǎng)站 6應用 7團體 8待審企業(yè) 200會員 220達人 0黃V用戶 其他藍v用戶 10是微女郎  
                        user_verified_type = user['verified_type']
                        user_urank = user['urank'] #微博等級
                        is_location = len(re.findall('small_location_default.png', text))
                        if is_location:
                            location = text_soup.find_all("span", {"class": "surl-text"})[-1].get_text()
                        else:
                            location = '' 

                        pic_num = len(mblog['pics']) if mblog.has_key('pics') else 0
                        info = (time, user_id, source, user_gender, user_statuses_count, user_followers_count, user_follow_count, \
                            user_verified, user_verified_type, user_urank, location, content, urls, pic_num, \
                            audios, mention, topic, reposts_count, comments_count, attitudes_count)
                        info_list.append(info)
                    
                    except Exception,e:
                        traceback.print_exc()
                        print '----'
                        print page
                        print 'since---'
                        print since_id
                        continue
                print 'get page:%d'%page
                page += 1

            return info_list
        except Exception,e:
            traceback.print_exc()
            return info_list
            
    #存入excel                 
    def save_excel(self):
        info_list = self.readHtml()
        #print info_list
        file = xlwt.Workbook()
        sheet1 = file.add_sheet(u'sheet1',cell_overwrite_ok=True)
        sheet1.col(0).width=256*22 
        sheet1.col(11).width=256*100 
        style = xlwt.easyxf('align: wrap on, vert centre, horiz center')
        row0 = ('time', 'user_id', 'source', 'user_gender', 'user_statuses_count', 'user_followers_count', \
        'user_follow_count', 'user_verified', 'user_verified_type', 'user_urank',\
        'location', 'content', 'urls', 'pic_num', 'audios', 'mention', 'topic', 'reposts_count', 'comments_count', 'attitudes_count')        
        for i in range(0,len(row0)):
            sheet1.write(0,i,row0[i],style)
        
        for i in range(0,len(info_list)):
            for j in range(0,len(info_list[i])):
                sheet1.write(i+1, j, info_list[i][j], style)
                
        file.save('D:/dataset/USele_topic.xls') 

        print  'save success'

#*******************************************************************************  
#                                程序入口 預先調用  
#*******************************************************************************  
      
if __name__ == '__main__':  
  
    WeiboContent().save_excel()
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,641評論 19 139
  • API定義規(guī)范 本規(guī)范設計基于如下使用場景: 請求頻率不是非常高:如果產品的使用周期內請求頻率非常高,建議使用雙通...
    有涯逐無涯閱讀 2,935評論 0 6
  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向對象的用電信息數(shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 12,446評論 6 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,172評論 25 708
  • 單身不可怕,最近,我總對自己這么說。 真真正談過三次戀愛,我常跟別人說,不美好,不美好,一點都不美好。即使是初戀!...
    995oo閱讀 382評論 2 2

友情鏈接更多精彩內容