4

在reddit URL中,有“5个字符数字”的thing_id部分(例如,“http://redd.it/wplf7”中的“wplf7”)是由base36生成的。

wplf7 是从数字 54941875 生成的 - 这是我到目前为止发现的......我想知道 54941875 是如何生成的。

我正在尝试使用 R 抓取 reddit 特定部分的评论(比如说http://www.reddit.com/r/leagueoflegends/),但我被困在这 5 个字符的数字上。

谁能用简单的方式解释一下?不幸的是,Python 不是我的领域,Reddit 网站上列出的 2000 行 Python 代码对我没有多大帮助。

谢谢,

4

2 回答 2

7

首先设置一个唯一的用户代理,因为 reddit 喜欢这样

options(HTTPUserAgent="My name is BOB")

我假设您想从http://www.reddit.com/r/leagueoflegends/获取内容。您需要将 a 附加.json到 url:

library(RJSONIO)
library(RCurl)
# library(XML)

jdata<-getURL('http://www.reddit.com/r/leagueoflegends/.json')
jdata<-fromJSON(jdata)
# xdata<-getURL('http://www.reddit.com/r/leagueoflegends/.xml')
# xdata<-xmlParse(xdata)

显然内容非常丰富,例如域名、永久链接、作者、帖子标题:

Domains<-sapply(jdata[[2]]$children,function(x){x$data$domain})
permalinks<-sapply(jdata[[2]]$children,function(x){x$data$permalink})
authors<-sapply(jdata[[2]]$children,function(x){x$data$author})
titles<-sapply(jdata[[2]]$children,function(x){x$data$title})
ids<-sapply(jdata[[2]]$children,function(x){x$data$id})
created<-as.POSIXct(sapply(jdata[[2]]$children,function(x){x$data$created}),origin="1970/01/01")


> head(titles)
[1] "Pendragon 3-day-banning someone for randoming in ranked, or saying hes going to. Mixed feelings..."
[2] "Dig Kicks L0cust."                                                                                 
[3] "Summoners, y u no communicate??"                                                                   
[4] "Without Even Trying"                                                                               
[5] "Cross Country Tryndamere (Chaox Stream)"                                                           
[6] "Top 5 Flops - Episode 4 ft Dyrus, Phantoml0rd, and HatPerson vs Baron Nashor"                      
> 

为了研究这些 id 是如何生成的,我们可以将@Ben Bolker 的base36ToInteger函数应用于我们收集的 id 并将它们与它们的创建日期进行比较:

createData<-data.frame(created=created,ids=sapply(ids,base36ToInteger))
> dput(createData)
structure(list(created = structure(c(1342658844, 1342657298, 
1342622962, 1342643655, 1342641187, 1342654768, 1342665353, 1342640599, 
1342648272, 1342662822, 1342654185, 1342659591, 1342624350, 1342647907, 
1342637587, 1342591960, 1342625515, 1342642330, 1342651384, 1342668363, 
1342608976, 1342608165, 1342632545, 1342638611, 1342643489), class = c("POSIXct", 
"POSIXt")), ids = c(55047001, 55044612, 55010018, 55025557, 55022809, 
55040754, 55056689, 55022221, 55031424, 55053023, 55039810, 55048123, 
55010880, 55030934, 55019343, 54976515, 55011555, 55024060, 55035670, 
55061120, 54998192, 54997264, 55015528, 55020295, 55025363)), .Names = c("created", 
"ids"), row.names = c("wrujd", "wrsp0", "wr202", "wrdzp", "wrbvd", 
"wrppu", "ws20h", "wrbf1", "wriio", "wrz6n", "wrozm", "wrvej", 
"wr2o0", "wri52", "wr973", "wqc5f", "wr36r", "wrcu4", "wrlsm", 
"ws5fk", "wqsvk", "wqs5s", "wr694", "wr9xj", "wrdub"), class = "data.frame")

在此处输入图像描述

这意味着随着新帖子的创建,reddit 会在整个网站上按顺序生成这些数字。

如果没有具体的方向,我会留在这里,但希望你能明白。

于 2012-07-18T22:51:11.770 回答
5

我从Erich Neuwirth 于 2008 年在 r-help 上发布的通用基本转换代码开始:这是递归的,所以可能很慢——但我花了合适的时间来开发它!

numberInBase <- function(number,base){
    numberInBaseRecur<-function(number,base){
        lastDigit<-function(number,base) number %% base
        if (number == 0) result <- c(0)
        else result <- c(numberInBaseRecur(number %/% base,base),
                         lastDigit(number,base))
        result
    }
    result <- numberInBaseRecur(number,base)
    while (result[1]== 0 && length(result)>1)
        result <- result[-1]
    result
} 

快速测试:

numberInBase(36^3,36)
## [1] 1 0 0 0

现在我们只需要从十进制转换为基数 36,然后索引适当的字母数字字符串。这是您的示例:

b36string <- c(0:9,letters)
paste(b36string[numberInBase(54941875,36)+1],collapse="")
## [1] "wplf7"

如果您需要另辟蹊径, Jim Holtman 于 2012 年 1 月发表的一篇文章给出了解决方案

base36ToInteger <- function (Str) {
    common <- chartr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
                     , ":;<=>?@ABCDEFGHIJKLMNOPQRS:;<=>?@ABCDEFGHIJKLMNOPQRS"
                     , Str)
    x <- as.numeric(charToRaw(common)) - 48
    sum(x * 36 ^ rev(seq(length(x)) - 1))
} 

base36ToInteger("wplf7")

(我还没有停下来弄清楚这实际上是如何工作的,但你可以阅读这篇文章......)

于 2012-07-18T00:56:40.917 回答