22、破解 Twitter 社交图数据:从理论到实践

破解 Twitter 社交图数据:从理论到实践

1. 项目背景与目标

在处理 Twitter 数据时,我们面临着严格的速率限制。为了避免触及这些限制并遵守 Twitter 的服务条款,我们将构建一个从 Twitter 提取数据的系统,且在整个过程中不直接访问 Twitter 的 API。

我们的项目从构建局部网络(即自我网络,ego - network)开始,采用类似计算 Erdős 数的方式进行雪球式扩展。我们的分析目标包括:探索社区检测方法,将社交网络划分为紧密的子群体,以了解特定用户所属的不同社交群体;利用 Twitter 社交图的结构构建“关注推荐”引擎。

2. 网络基础概念

在深入研究 Twitter 社交图之前,我们需要明确网络的基本概念。从数学角度看,网络(或图)是由节点和边组成的集合。这些集合本身没有特定的上下文,仅用于表示边连接节点的某种世界。

下面是不同类型网络的介绍:
| 网络类型 | 特点 | 示例 |
| ---- | ---- | ---- |
| 无向网络 | 边没有方向,节点间的连接意味着相互关系 | 如图 11 - 2 顶部面板所示,Dick 和 Harry 共享连接,可相互交换信息、物品等 |
| 有向网络 | 边有箭头表示方向,体现单向关系 | 图 11 - 2 中间面板中,Dick 和 Drew 与 John 有连接,但 John 仅与 Harry 有连接 |
| 带标签边的有向网络 | 在有向网络基础上,边添加了标签,可表示“喜欢”“不喜欢”关系或访问级别等 | 图 11 - 2 最后面板,边标签可以是更复杂的权重,指示关系的强度或类型 |

不同的社交网络使用不同类型的图,例如 Facebook 是大规模的无向社交图,“加好友”需要双方同意,所有边都意味着相互的友谊,形成相对封闭、局部网络结构密集的网络;而 Twitter 是大型有向图,关注关系无需相互同意,允许图中存在较大的不对称性,名人、新闻媒体等成为主要的推文传播点。

3. 选择数据来源

Twitter 提供两种 API 访问方式:未认证访问每小时允许 150 次请求,OAuth 认证访问每小时限制为 350 次请求。这两种限制都无法在合理时间内满足我们的数据抓取需求,且我们不希望构建需要认证的 Twitter 应用。

因此,我们选择使用 Google 的 SocialGraph API(SGA)来获取 Twitter 社交图数据。SGA 于 2008 年推出,旨在创建跨所有社交网络站点的单一在线身份。通过输入以下 URL 并替换 EMAIL_ADDRESS,可查看 Google 存储的个人社交图数据:

https://socialgraph.googleapis.com/lookup?q=@EMAIL_ADDRESS&fme=1&pretty=1

SGA 会爬取包括 Twitter 在内的多个社交网络站点,存储公共社交图数据。其主要优势是每天允许 50,000 次查询,足以构建绝大多数用户的社交图。

4. 使用 SGA 查询数据

以 Drew 的 Twitter 页面为例,使用以下 API 查询:

https://socialgraph.googleapis.com/lookup?q=http://twitter.com/drewconway&edo=1&edi=1&pretty=1

该查询包含三个重要参数:
- pretty :仅在浏览器查看时有用,返回格式化的 JSON。在解析 JSON 构建网络时可忽略此参数。
- edo :表示“外向边”,即 Twitter 好友。
- edi :表示“内向边”,即 Twitter 粉丝。

查询返回的 JSON 中,我们主要关注 nodes 对象,它包含 Twitter 用户的描述信息以及入站和出站关系。 nodes_referenced 对象包含被查询节点关注的用户(出度), nodes_referenced_by 对象包含关注被查询节点的用户(入度)。

以下是示例 JSON 结构:

{
 "canonical_mapping": {
  "http://twitter.com/drewconway": "http://twitter.com/drewconway"
 },
 "nodes": {
  "http://twitter.com/drewconway": {
   "attributes": {
    "exists": "1",
    "bio": "Hopeful academic, data nerd, average hacker, student of conflict.",
    "profile": "http://twitter.com/drewconway",
    "rss": "http://twitter.com/statuses/user_timeline/drewconway.rss",
    "atom": "http://twitter.com/statuses/user_timeline/drewconway.atom",
    "url": "http://twitter.com/drewconway"
   },
   "nodes_referenced": {
      ...
   },
   "nodes_referenced_by": {
      ...
   }
  }
}

需要注意的是,SGA 爬虫仅扫描 Twitter 用户的公共链接,私人 Twitter 账户的数据不会包含在内。而且,由于 SGA 定期爬取活动链接,其缓存数据可能不反映最新的 Twitter 关系。

5. 构建网络的 R 代码实现

为了使用 SGA 数据构建 Twitter 网络,我们需要使用 R 语言和相关包。以下是具体步骤:

5.1 加载必要的 R 包
library(RCurl)
library(RJSONIO)
library(igraph)
5.2 编写核心函数
  • twitter.network 函数 :查询 SGA 获取指定种子用户的 JSON 数据,并解析为自我网络。
twitter.network <- function(user) {
  api.url <- paste("https://socialgraph.googleapis.com/lookup?q=http://twitter.com/",
                   user, "&edo=1&edi=1", sep="")
  api.get <- getURL(api.url)
  while(grepl("Service Unavailable. Please try again later.", api.get)) {
    api.get <- getURL(api.url)
  }
  api.json <- fromJSON(api.get)
  return(build.ego(api.json))
}
  • find.twitter 函数 :从节点向量中筛选出真正的 Twitter 用户节点。
find.twitter <- function(node.vector) {
  twitter.nodes <- node.vector[grepl("http://twitter.com/", node.vector, fixed=TRUE)]
  if(length(twitter.nodes) > 0) {
    twitter.users <- strsplit(twitter.nodes, "/")
    user.vec <- sapply(1:length(twitter.users),
                       function(i) (ifelse(twitter.users[[i]][4]=="account",
                                           NA, twitter.users[[i]][4])))
    return(user.vec[which(!is.na(user.vec))])
  } else {
    return(character(0))
  }
}
  • build.ego 函数 :根据解析的 JSON 数据构建自我网络的边列表。
build.ego <- function(json) {
  ego <- find.twitter(names(json$nodes))
  nodes.out <- names(json$nodes[[1]]$nodes_referenced)
  if(length(nodes.out) > 0) {
    twitter.friends <- find.twitter(nodes.out)
    if(length(twitter.friends) > 0) {
      friends <- cbind(ego, twitter.friends)
    } else {
      friends <- c(integer(0), integer(0))
    }
  } else {
    friends <- c(integer(0), integer(0))
  }
  nodes.in <- names(json$nodes[[1]]$nodes_referenced_by)
  if(length(nodes.in) > 0) {
    twitter.followers <- find.twitter(nodes.in)
    if(length(twitter.followers) > 0) {
      followers <- cbind(twitter.followers, ego)
    } else {
      followers <- c(integer(0), integer(0))
    }
  } else {
    followers <- c(integer(0), integer(0))
  }
  ego.el <- rbind(friends, followers)
  return(ego.el)
}
  • get.seeds 函数 :从边列表中找出非种子节点的唯一节点集合。
get.seeds <- function(snowball.el, seed) {
  new.seeds <- unique(c(snowball.el[,1],snowball.el[,2]))
  return(new.seeds[which(new.seeds!=seed)])
}
  • twitter.snowball 函数 :实现雪球采样,构建完整的网络。
twitter.snowball <- function(seed, k=2) {
  snowball.el <- twitter.network(seed)
  new.seeds <- get.seeds(snowball.el, seed)
  rounds <- 1
  all.nodes <- seed
  while(rounds < k) {
    next.seeds <- c()
    for(user in new.seeds) {
      if(!user %in% all.nodes) {
        user.el <- twitter.network(user)
        if(dim(user.el)[2] > 0) {
          snowball.el <- rbind(snowball.el, user.el)
          next.seeds <- c(next.seeds, get.seeds(user.el, user))
          all.nodes <- c(all.nodes, user)
        }
      }
    }
    new.seeds <- unique(next.seeds)
    new.seeds <- new.seeds[!which(new.seeds %in% all.nodes)]
    rounds <- rounds + 1
  }
  snowball.el <- snowball.el[!duplicated(snowball.el),]
  return(graph.edgelist(snowball.el))
}

以下是雪球采样的流程图:

graph TD;
    A[开始] --> B[获取种子用户的自我网络];
    B --> C[找出新种子节点];
    C --> D{是否达到采样轮数};
    D -- 否 --> E[遍历新种子节点];
    E --> F{节点是否已访问};
    F -- 否 --> G[获取节点的自我网络];
    G --> H[更新边列表和新种子节点列表];
    H --> I[更新已访问节点列表];
    I --> E;
    F -- 是 --> E;
    D -- 是 --> J[去除边列表中的重复行];
    J --> K[转换为 igraph 图对象];
    K --> L[结束];

通过以上步骤,我们可以构建 Twitter 网络。接下来,我们将构建补充脚本,以便从给定的种子用户快速生成网络结构,并对这些图进行基本的结构分析,以发现其中的局部社区结构。

破解 Twitter 社交图数据:从理论到实践

6. 补充脚本构建与网络分析

在完成核心网络构建函数的编写后,我们可以进一步构建补充脚本,用于快速生成网络结构并进行基本的结构分析,以发现 Twitter 网络中的局部社区结构。

6.1 快速生成网络结构

利用之前编写的 twitter.snowball 函数,我们可以轻松地从指定的种子用户开始构建网络。以下是一个简单的示例,展示如何使用该函数:

# 选择一个种子用户
seed_user <- "drewconway"
# 进行两轮雪球采样
twitter_network <- twitter.snowball(seed_user, k = 2)

在这个示例中,我们选择了 drewconway 作为种子用户,并进行了两轮雪球采样,最终得到了一个 igraph 图对象 twitter_network

6.2 基本结构分析

得到网络对象后,我们可以使用 igraph 包提供的各种函数进行基本的结构分析。以下是一些常见的分析方法:
- 节点数量 :查看网络中包含的节点数量。

num_nodes <- vcount(twitter_network)
print(paste("网络中的节点数量:", num_nodes))
  • 边的数量 :查看网络中边的数量。
num_edges <- ecount(twitter_network)
print(paste("网络中的边数量:", num_edges))
  • 度分布 :分析节点的度分布,了解节点的连接情况。
degree_distribution <- degree(twitter_network)
hist(degree_distribution, main = "节点度分布", xlab = "节点度", ylab = "节点数量")
  • 社区检测 :使用 igraph 包中的社区检测算法,将网络划分为不同的社区。
# 使用 Louvain 算法进行社区检测
communities <- cluster_louvain(twitter_network)
# 查看社区数量
num_communities <- length(communities)
print(paste("检测到的社区数量:", num_communities))

以下是一个简单的表格,总结了上述分析方法及其作用:
| 分析方法 | 作用 |
| ---- | ---- |
| 节点数量 | 了解网络的规模 |
| 边的数量 | 了解网络的连接密度 |
| 度分布 | 分析节点的连接情况 |
| 社区检测 | 发现网络中的局部社区结构 |

7. 注意事项与拓展思考

在使用上述方法构建和分析 Twitter 网络时,有一些注意事项需要我们关注:
- 数据准确性 :由于 SGA 的数据可能存在不准确性,如缓存数据不反映最新的 Twitter 关系,我们在分析结果时需要谨慎对待。可以结合其他数据源或进行多次采样来提高数据的准确性。
- 速率限制 :虽然 SGA 每天允许 50,000 次查询,但对于一些大规模的网络构建,仍然可能会受到速率限制的影响。在实际应用中,我们可以合理安排查询时间,避免短时间内进行大量查询。
- 内存管理 :在处理大规模网络时,内存管理尤为重要。我们可以采用分批处理、及时释放不再使用的对象等方法来优化内存使用。

此外,我们还可以对现有方法进行拓展和改进:
- 多轮采样 :可以增加雪球采样的轮数,以获取更广泛的网络结构,但需要注意速率限制和内存使用。
- 结合其他数据源 :除了 SGA,还可以结合 Twitter 的官方 API 或其他第三方数据源,以获取更全面的 Twitter 数据。
- 更复杂的分析方法 :可以使用更复杂的社区检测算法、中心性分析等方法,深入挖掘 Twitter 网络的结构和特征。

以下是一个拓展思考的流程图,展示了如何对现有方法进行拓展和改进:

graph TD;
    A[现有方法] --> B[增加采样轮数];
    A --> C[结合其他数据源];
    A --> D[使用更复杂的分析方法];
    B --> E[获取更广泛的网络结构];
    C --> F[获取更全面的数据];
    D --> G[深入挖掘网络特征];
    E --> H[优化速率限制和内存使用];
    F --> H;
    G --> H;
    H --> I[改进后的方法];
8. 总结

通过本文的介绍,我们详细阐述了如何在不直接访问 Twitter API 的情况下,利用 Google 的 SocialGraph API 构建 Twitter 网络,并进行基本的结构分析。具体步骤如下:
1. 明确项目背景和目标,了解网络的基本概念,包括无向网络、有向网络和带标签边的有向网络。
2. 选择合适的数据来源,即 Google 的 SocialGraph API,并了解其查询参数和返回数据的结构。
3. 使用 R 语言和相关包编写核心函数,包括 twitter.network find.twitter build.ego get.seeds twitter.snowball 函数,实现网络的构建和雪球采样。
4. 构建补充脚本,快速生成网络结构并进行基本的结构分析,如节点数量、边的数量、度分布和社区检测等。
5. 注意数据准确性、速率限制和内存管理等问题,并对现有方法进行拓展和改进。

通过这些步骤,我们可以深入了解 Twitter 网络的结构和特征,为进一步的社交网络分析和应用提供基础。希望本文对您在处理 Twitter 数据和构建社交网络方面有所帮助。

MATLAB主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性内容概要:本文主要介绍了一种在MATLAB环境下实现的主动噪声和振动控制算法,该算法针对较大的次级路径变化具有较强的鲁棒性。文中详细阐述了算法的设计原理与实现方法,重点解决了传统控制系统中因次级路径动态变化导致性能下降的问题。通过引入自适应机制和鲁棒控制策略,提升了系统在复杂环境下的稳定性和控制精度,适用于需要高精度噪声与振动抑制的实际工程场景。此外,文档还列举了多个MATLAB仿真实例及相关科研技术服务内容,涵盖信号处理、智能优化、机器学习等多个交叉领域。; 适合人群:具备一定MATLAB编程基础和控制系统理论知识的科研人员及工程技术人员,尤其适合从事噪声与振动控制、信号处理、自动化等相关领域的研究生和工程师。; 使用场景及目标:①应用于汽车、航空航天、精密仪器等对噪声和振动敏感的工业领域;②用于提升现有主动控制系统对参数变化的适应能力;③为相关科研项目提供算法验证与仿真平台支持; 阅读建议:建议读者结合提供的MATLAB代码进行仿真实验,深入理解算法在不同次级路径条件下的响应特性,并可通过调整控制参数进一步探究其鲁棒性边界。同时可参考文档中列出的相关技术案例拓展应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值