python-新浪爬取话题微博实践

说完模拟登录之后呢,现在讲述对于手机端新浪的爬取过程,此例讲述针对Ajax异步请求内容的爬取,以新浪微博“小黄车”话题下的微博为例

分析过程####

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

2.微博信息所在位置查找
当你进入该话题时,通过查看源代码发现里面并没有页面上的微博信息,那么这些信息在哪呢?是怎么载入到页面的呢?打开开发者工具,当你鼠标滑到页面底端时继续滑动会加载出新的页面,这个时候会发现网络中的XHR请求会对应增加一项,并且查看响应会发现里面包含了页面的各种信息。主题微博信息第一页在cards的第五个对象下的cardgroup中,其余页面均在cards的第一个对象下的cardgroup中如下图

Paste_Image.png
Paste_Image.png

发现页面内容所在之后就需要构造类似的请求,以得到包含微博信息的响应json文件。
3.请求规律
那么,又一个问题来了,请求有什么规律呢?请求可在标题头中查看,具体可点击编辑和重发查看具体信息,具体参数可在参数中查看

Paste_Image.png

加载新一页之后发现这些请求除了since_id这项参数是不一样的之外,其余都是一样的,也就是说话题下的微博分页是根据since_id来确定的,每当页面滑倒底部时,继续往下滑则会发送新的请求,请求中的since_id标志上一页加载到哪一条微博,现在应该从哪一条微博开始展示。这样就实现了分页,因此,接下来就是找到since_id的内容来源于哪里就可以开始构造请求了,经查看后发现每一个请求的since_id内容都可以在前一项请求中的响应中找到

Paste_Image.png

代码讲解####

1.思路介绍
首先构造请求,第一页是没有since_id参数的,所以除since_id外的请求参数可固定,since_id则通过每一次读取响应内容中的since_id动态替换,然后成功读取响应内容后(响应内容为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 
           #构造固定的一些参数
            form_data = {
                'extparam' : '小黄车',
                'from' : 'feed',
                'luicode' : '10000011',
                'lfid' : '100808b0a0455a95cc4937460d29aa3076aec4',
                'containerid' : '100808topic'

            }
            since_id = ''
            #这里是以since_id为循环终止条件,最后一页没有since_id,所以当获取出错时跳出循环
            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 #这里写的比较随意,直接给出日期,可利用和时间有关函数动态获取爬取当天的日期
                        #获取微博内容,如果为长微博需获取全文的链接地址进一步获取微博全部内容
                        isLongText = mblog['isLongText']
                        text = mblog['text']
                        if isLongText:
                            text_id = mblog['id']
                            text_href = 'http://m.weibo.cn/statuses/extend?id=%s'%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'] #微博数
                        user_followers_count = user['followers_count'] #粉丝数
                        user_follow_count = user['follow_count'] #关注数
                        user_verified = user['verified']
                        #verified_type:-1普通用户 0名人 1政府 2企业 3媒体 4校园 5网站 6应用 7团体 8待审企业 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()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • API定义规范 本规范设计基于如下使用场景: 请求频率不是非常高:如果产品的使用周期内请求频率非常高,建议使用双通...
    有涯逐无涯阅读 2,442评论 0 6
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,507评论 6 13
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 单身不可怕,最近,我总对自己这么说。 真真正谈过三次恋爱,我常跟别人说,不美好,不美好,一点都不美好。即使是初恋!...
    995oo阅读 325评论 2 2