药大贴吧用户数据资料爬取与简单分析

 使用python爬虫连接到药大贴吧的首页,然后爬取每个话题的链接。将链接记录到一个列表中。打开列表中的链接,读取第一页页的用户的主页链接和话题下的帖子页数。将用户的主页连接记录到一个集合中。如果发现有多页,就记录每一页的连接,再从这些连接中读取用户的主页连接记录到集合中。这样可爬取首页下所有用户的主页url。
 依次从集合中取出URL,打开主页,记录用户名称,性别,粉丝数,关注者的信息,发帖量等资料。
    #coding:utf-8
import urllib2
import re
from bs4 import BeautifulSoup
from numpy import unique
import time
from pandas import *
#从主页上提取用户的昵称,关注者数量,粉丝数量,粉丝连接,关注者的连接,吧年龄,帖子数量,性别
import socket
timeout =20
socket.setdefaulttimeout(timeout)                                      #设置20秒超时断开连接

class userinfo(object):
    def __init__(self,url):
        self.url = url
        self.username = None
        self.concern_num = None
        self.fans_num = None
        self.age = None
        self.tie = None
        self.sex = None
        self.concern_link = None
        self.fans_link = None
    def get_fans(self):
        return self.fans_link
    def get_concern(self):
        return self.concern_link

def urlget(url):
    print url
    user = userinfo(url)
    prefix="http://tieba.baidu.com"
    web_doc = urllib2.urlopen(url).read()
    soup = BeautifulSoup(web_doc,"html.parser",from_encoding="utf-8")
    try:
        username = soup.find_all(‘span‘,attrs={‘class‘:‘userinfo_username ‘})[0].get_text()       #获取网页上的用户的名称
        print "username=",username
        user.username = username
    except IndexError:
        print "username_error"
        print url
    try:
        concernlst = soup.find_all(‘span‘,attrs={‘class‘:"concern_num"})
        concern_link = concernlst[0].find_all(‘a‘,attrs={‘href‘:True,‘target‘:‘_blank‘})[0][‘href‘]
        concern_link = prefix+concern_link     #关注连接
        user.concern_link = concern_link
        concern_num = concernlst[0].find_all(‘a‘,attrs={‘href‘:True,‘target‘:‘_blank‘})[0].get_text()
        print "concern_num=",float(concern_num)
    except IndexError:
        print "concern_error----"
        print url
    try:
        fans_link = concernlst[1].find_all(‘a‘,attrs={‘href‘:True,‘target‘:‘_blank‘})[0][‘href‘]
        fans_link = prefix + fans_link            #粉丝连接
        user.fans_link = fans_link
        fans_num = concernlst[1].find_all(‘a‘,attrs={‘href‘:True,‘target‘:‘_blank‘})[0].get_text()
        print "fans_num=",fans_num
        user.fans_num = int(fans_num)
    except IndexError:
        print "fans_error-----------------------"
        print url
    try:
        infor = soup.find_all(‘div‘,attrs={‘class‘:‘userinfo_userdata‘})[0]
        agetie = infor.find_all(‘span‘,attrs={‘class‘:False})
        print "age=",agetie[0].get_text()[3:-1]       #第一个是吧年龄,第二个是帖子数量
        user.age = agetie[0].get_text()[3:]
        print "tie=",agetie[1].get_text()[3:]
        user.tie = agetie[1].get_text()[3:]
        p_sex = re.compile(r‘userinfo_sex.*‘)
        print infor.find_all(‘span‘,attrs={‘class‘:p_sex})[0]
        sexstr = infor.find_all(‘span‘,attrs={‘class‘:p_sex})[0][‘class‘][1]  #提取用户的性别
        print "the sex of the user is : "
        if "female" in sexstr:
            print "female"
            user.sex = "female"
        elif "male" in sexstr:
            print "male"
            user.sex = "male"
        else:
            print "no sex"
            user.sex = "no sex"
    except IndexError:
        print "infor_error"
        print url
    return user

‘‘‘提取关注者主页‘‘‘
def getconcern(url):
    concern_lst = getfans(url)          #输出关注者的页面连接
    return concern_lst

‘‘‘提取粉丝主页‘‘‘
def getfans(url):
    prefix="http://tieba.baidu.com"
    print url
    web_doc = urllib2.urlopen(url).read()
    soup = BeautifulSoup(web_doc,"html.parser",from_encoding="utf-8")
    span = soup.find_all(‘span‘,attrs={‘class‘:‘name‘})
    p_href = re.compile(‘/home/main.*‘);home_lst=[]
    for s in span:
        homelink = s.find_all(‘a‘,attrs={‘href‘:p_href,‘target‘:‘_blank‘})[0][‘href‘]
        print homelink
        homelink = prefix + homelink
        home_lst.append(homelink)
    return home_lst

‘‘‘从当前的主题的连接中提取人员的主页连接,输入为一个url,返回当前用户主页连接集合,并且所有页的连接‘‘‘
#提取用户连接,再判断有多少页,确定页码数量。构建连接
def homeget(url):
    web_doc = urllib2.urlopen(url).read()
    time.sleep(1)
    print "homeset,sleeping..."
    soup = BeautifulSoup(web_doc,"html.parser",from_encoding="utf-8")
    p_home = re.compile(r‘/home/main?.*‘)
    homenode = soup.find_all(‘a‘,attrs={‘href‘:p_home,‘target‘:‘_blank‘,‘class‘:‘p_author_face ‘}) #主页节点
    prefix = "http://tieba.baidu.com/"
    linklst = [prefix + home[‘href‘] for home in homenode]   #提取到用户主页的连接的列表
    try:
        locate = soup.find_all(‘li‘,attrs={‘class‘:‘l_pager pager_theme_5 pb_list_pager‘})[0]
    except:
        print url
        return unique(linklst),[]
    alst = locate.find_all(‘a‘,attrs={"href":True})
    if alst == []:
        return unique(linklst),[]
    else:
        href = alst[len(alst)-1][‘href‘]
        pagenum  = int(href.split(‘=‘)[1])  #确认数量
        pagelst = []
        prefix = "http://tieba.baidu.com/"
        for i in range(2,pagenum+1):
            page_link = prefix + href.split("=")[0] + "=" + str(i)
            pagelst.append(page_link)
        return unique(linklst),pagelst

‘‘‘给定连接集合,循环提取所有的用户主页连接,组成集合并返回一个集合‘‘‘
def pagesget(page_lst):
    if page_lst == [] : return set()
    prefix = "http://tieba.baidu.com/"
    totalset=set()
    for page in page_lst:
        web_doc = urllib2.urlopen(page).read()
        time.sleep(1)
        print "pagesget,sleeping..."
        soup = BeautifulSoup(web_doc,"html.parser",from_encoding="utf-8")
        p_home = re.compile(r‘/home/main?.*‘)
        homenode = soup.find_all(‘a‘,attrs={‘href‘:p_home,‘target‘:‘_blank‘}) #主页节点,‘class‘:‘p_author_face ‘
        linklst = [prefix + home[‘href‘] for home in homenode]   #提取到用户主页的连接的列表
    totalset = totalset | set(linklst)
    return totalset

‘‘‘给定贴吧,提取贴吧第一页的各个主题的连接‘‘‘
def topicenter(url="http://tieba.baidu.com/f?kw=%D6%D0%B9%FA%D2%A9%BF%C6%B4%F3%D1%A7"):
    web_doc = urllib2.urlopen(url).read()
    soup = BeautifulSoup(web_doc,"html.parser",from_encoding="utf-8")
    p = re.compile(r‘/p/\d{10}‘)
    theme_url = soup.find_all(‘a‘,attrs={‘href‘:p,‘title‘:True,‘target‘:‘_blank‘,‘class‘:‘j_th_tit‘})
    prefix = "http://tieba.baidu.com";url_lst=[]
    for theme in set(theme_url):                                  #主题连接补充完整
        theme = prefix + theme[‘href‘]
        url_lst.append(theme)
        print "current theme is:"
        print theme
    theme_page = soup.find_all(‘a‘,attrs={‘class‘:‘ pagination-item ‘})
    theme_page_links = [theme[‘href‘] for theme in theme_page]
    return url_lst,theme_page_links

‘‘‘提取主题列表第2页到第10的内容‘‘‘
def get_themes(theme_page_links):
    if theme_page_links == []:return None
    p = re.compile(r‘/p/\d{10}‘);url_lst=[]
    for theme in theme_page_links:
        web_doc = urllib2.urlopen(theme).read()
        print "sleeping......"
        print "theme_url=",theme
        time.sleep(1)
        soup = BeautifulSoup(web_doc,"html.parser",from_encoding="utf-8")
        theme_url = soup.find_all(‘a‘,attrs={‘href‘:p,‘title‘:True,‘target‘:‘_blank‘,‘class‘:‘j_th_tit‘})
        prefix = "http://tieba.baidu.com";
        for theme in set(theme_url):                                  #主题连接补充完整
            theme = prefix + theme[‘href‘]
            url_lst.append(theme)
    return url_lst

otherthemes = get_themes(pages)
pages = set(themes) | set(otherthemes)    #获得前十页的主题的连接
user_url = set();k=0                    #存放用户的主页链接
for pg in pages:
    curruser,pagetalk = homeget(pg)      #主题下的第一页的用户的内容和剩余页的连接
    try:
        nextuser = pagesget(pagetalk)        #剩余页的用户主页连接
    except:
        break
    themeuser = set(curruser) | nextuser #这个主题下的所有用户的主页连接
    user_url = user_url | themeuser      #合并到所有的用户中去
    print "current number is ",len(user_url)
    if len(user_url) > 902:break

print "the number of active username in baidutieba is: ",len(user_url)                      #统计用户数量

user_dic={}                              #记录用户的内容
for i in user_url:
    user = urlget(i)
    if user.username not in user_dic.keys():
        user_dic[user.username] = {‘url‘:user.url,‘concern_num‘:user.concern_num,‘fans_num‘:user.fans_num,‘age‘:user.age,‘tie‘:user.tie,‘sex‘:user.sex,‘concern_link‘:user.concern_link,‘fans_link‘:user.fans_link}

运行爬虫抓取信息要花十几分钟的时间,每次都记录主页连接集合的数量增长,发现在增长至905人后就停止了。而且贴吧的话题页的下一页连接虽然被获取,但是在打开后会跳转到第一页,这个会导致信息的重复爬取,浪费时间。因此,在905个连接之后就停止了爬取。打开主页爬取各个信息存放在一个对象中。由于中文支持不是很给力(之前是写入到记事本中,这次写入csv失败了),把输出结果复制在记事本中。写一个程序整理一下输出结果:

#coding:utf-8
from pandas import *

def loadfile(filename):
    f = open(filename)
    userinfor={};dic={};order=0
    for i in f.readlines():
        i = i.strip()
        if ‘http‘ in i:continue
        if ‘the sex of‘ in i :continue
        if ‘span‘ in i :continue
        if "username" in i: #新出现一个人
            userinfor[str(order)] = dic  #收集的数据保存到总的信息中
            order += 1              #更新顺序
            dic={‘userno‘:order,‘concernum‘:0,‘age‘:0,‘tie‘:0,‘sex‘:‘unknown‘,‘fans_num‘:0}      #篮子清空
        if (‘concern_num‘ in i) and (‘error‘ not in i):
            num = float(i.split(‘=‘)[1].strip())
            dic[‘concernum‘] = num
        if (‘age‘ in i) and (‘error‘ not in i) :
            try:
                age = float(i[4:].strip())
            except ValueError:
                print i
            dic[‘age‘] = age
        if (‘tie‘ in i) and (‘error‘ not in i) :
            try:
                tie = float(i.split(‘=‘)[1].strip())
                print i
            except ValueError:
                print i
                tie = float(i[4:].strip()[:-2])*10000.0
            dic[‘tie‘] = tie
        if (‘male‘ in i) and len(i)<=6:
            dic[‘sex‘] = i.strip()
        if (‘fans_num‘ in i) and (‘error‘ not in i):
            num = float(i.split(‘=‘)[1].strip())
            dic[‘fans_num‘] = num
    return userinfor

filename = ‘E://information.txt‘
dic = loadfile(filename)
dic.pop(‘0‘)
df = DataFrame(dic)
df = df.T
df.to_csv("E://infor.csv")

最后整理出来的信息是一个csv文件,一行是一个人的记录,使用编号表示。属性是吧龄,关注人的数量,粉丝数量,性别和帖子数量。使用R语言读取该csv文件进行分析。主要是分析男性和女性在一些信息上是否存在差异。使用帖子数量除以吧龄的值表示发帖的频率。

贴吧上的男女比例:

统计一下不同性别下吧龄分布情况:大部分的人的吧龄处于2年以下,多于两年的人不多,6年以上的人很少。

如果按照发帖量升序排序,横坐标为排名,纵坐标为帖子数量,作图,发现排名靠前的相邻排名的用户的帖子数量差距巨大,但随着排名靠后的人差距不明显,可见在发帖量上存在二八效应(20%的人帖子数量占据了总帖子数量的80%):

在逛贴吧这种事情上,女生人均发帖数量与男生不同,存在95%以上的显著性差异,女生的发帖量更大。在发帖的频率上,90%的显著水平,男生女生存在差异,女生频率更高。

这次爬取不足之处:

需要解决重定向的问题,如何进入到帖吧的下一页;

中文处理,在用户名上有各种各样的文字,字母和汉字,甚至还有颜文字和假名等等,这些如何保存;

时间: 2024-07-29 16:20:33

药大贴吧用户数据资料爬取与简单分析的相关文章

python实现人人网用户数据爬取及简单分析

这是之前做的一个小项目.这几天刚好整理了一些相关资料,顺便就在这里做一个梳理啦~ 简单来说这个项目实现了,登录人人网并爬取用户数据.并对用户数据进行分析挖掘,终于效果例如以下:1.存储人人网用户数据(户主的全部好友.户主好友的全部好友.户主及好友关注的公共主页).2.信息可视化,绘制户主好友间的关系网络图:3.数据挖掘,通过分析户主好友关注的公共主页,向户主推荐公共主页. 项目分为三个部分,各自是人人网登录及用户数据爬取与存储.用户关系可视化.公共主页推荐.以下分别介绍这三个部分. 第一部分实现

抓取百万知乎用户数据之爬取思路

一.如何获取到用户的信息 前往用户主页,以轮子哥为例 从中可以看到用户的详细信息,教育经历主页,主修.所在行业,公司,关注量,回答数,居住地等等.打开开发者工具栏查看网络,即可找到,一般是html或者json这个数据在Html页面里. URL为https://www.zhihu.com/people/excited-vczh/answers,excited-vczh是轮子哥的id,我们只要拿到某个人的Id就可以获取详细信息了. 二.信息藏在哪 对这个json数据进行解析,即可找到用户信息 根据U

python爬虫入门 之 移动端数据的爬取

第七章 移动端数据的爬取 基于某一款抓包工具 : fiddler ,青花瓷 ,miteproxy 7.1 fiddler 基本配置 7.1.1fiddler简介和安装 什么是Fiddler? Fiddler是位于客户端和服务器端的HTTP代理,也是目前最常用的http抓包工具之一 . 它能够记录客户端和服务器之间的所有 HTTP请求,可以针对特定的HTTP请求,分析请求数据.设置断点.调试web应用.修改请求的数据,甚至可以修改服务器返回的数据,功能非常强大,是web调试的利器. Fiddler

使用 Chrome 浏览器插件 Web Scraper 10分钟轻松实现网页数据的爬取

本文标签: WebScraper Chrome浏览器插件 网页数据的爬取 使用Chrome 浏览器插件 Web Scraper 可以轻松实现网页数据的爬取,不写代码,鼠标操作,点哪爬哪,还不用考虑爬虫中的登陆.验证码.异步加载等复杂问题. Web Scraper插件 Web Scraper 官网中的简介: Web Scraper Extension (Free!)Using our extension you can create a plan (sitemap) how a web site

雪球数据的爬取

import requests from lxml import etree import json import pymongo # 连接mongodb 数据库 存mongodb中 client = pymongo.MongoClient('127.0.0.1', port=27017) db = client.xueqiu collection = db.xueqiu url = 'https://xueqiu.com/' headers = { "User-Agent": &qu

python爬虫---CrawlSpider实现的全站数据的爬取,分布式,增量式,所有的反爬机制

CrawlSpider实现的全站数据的爬取 新建一个工程 cd 工程 创建爬虫文件:scrapy genspider -t crawl spiderName www.xxx.com 连接提取器LinkExtractor 可以根据指定的规则对指定的连接进行提取 提取的规则就是构造方法中的allow('正则表达式')参数决定 规则解析器Rule 可以将将连接提取器提取到的连接进行请求发送,可以根据指定的规则(callback)对请求到的数据进行解析 follow=True:将连接提取器 继续作用到

爬虫入门五(移动端数据的爬取)

常用的抓包工具 常用的抓包工具:本质就是一款服务器,适用于实现请求和响应的拦截 fiddler 默认只可以抓起http协议的请求和响应 https: tools - options - https - detrypt https traffic 含义:将fiddler的证书安装到本地 青花瓷(charles) miteproxy 移动端数据的爬取 配置相关的环境 fiddler的配置: tools->options->connections->allow remote conxxx 查看

【实例】--股票数据定向爬取

从股票列表网页获取股票代码 根据股票代码去股票详情页面获取股票详细信息 1. 股票列表页面 凤凰网财经—股票信息 http://app.finance.ifeng.com/list/stock.php?t=ha&f=chg_pct&o=desc&p=1 2. 股票详细信息 老虎社区—股票详情 https://www.laohu8.com/stock/600210 股票数据定向爬取思路 1. 查看网站robots协议,查看网站是否可以爬取 2. 查看网页源代码,查看网页信息是否可以直

java爬取网页内容 简单例子(2)——附jsoup的select用法详解

http://www.cnblogs.com/xiaoMzjm/p/3899366.html [背景] 在上一篇博文java爬取网页内容 简单例子(1)——使用正则表达式 里面,介绍了如何使用正则表达式去解析网页的内容,虽然该正则表达式比较通用,但繁琐,代码量多,现实中想要想出一条简单的正则表达式 对于没有很好正则表达式基础的人——比如说我T_T——是一件蛮困难的事.这一篇,我们改用jsoup,一个强大的解析html工具,去解析html,你会发现,一切都变得很容易. [准备工作] 下载:jsou