使用R中的正则表达式获取Twitter @用户名

4
如何在R中使用正则表达式从文本字符串中提取Twitter用户名?
我尝试过:
library(stringr)

theString <- '@foobar Foobar! and @foo (@bar) but not foo@bar.com'

str_extract_all(string=theString,pattern='(?:^|(?:[^-a-zA-Z0-9_]))@([A-Za-z]+[A-Za-z0-9_]+)')

但我最终得到了@foobar@foo(@bar,其中包含一个不想要的括号。

如何只输出@foobar@foo@bar

3个回答

8
这里有一种在R中有效的方法:
theString <- '@foobar Foobar! and @foo (@bar) but not foo@bar.com'
theString1 <- unlist(strsplit(theString, " "))
regex <- "(^|[^@\\w])@(\\w{1,15})\\b"
idx <- grep(regex, theString1, perl = T)
theString1[idx]
[1] "@foobar" "@foo"    "(@bar)"

如果您想在R中使用@Jerry的答案:

regex <- "@([A-Za-z]+[A-Za-z0-9_]+)(?![A-Za-z0-9_]*\\.)"
idx <- grep(regex, theString1, perl = T)
theString1[idx]
[1] "@foobar" "@foo"    "(@bar)" 

这两种方法都包含了你不想要的括号。

更新 这将让你从头到尾完成,没有任何括号或其他标点符号(除了下划线,因为它们在用户名中是允许的)。

theString <- '@foobar Foobar! and @fo_o (@bar) but not foo@bar.com'
theString1 <- unlist(strsplit(theString, " "))
regex1 <- "(^|[^@\\w])@(\\w{1,15})\\b" # get strings with @
regex2 <- "[^[:alnum:]@_]"             # remove all punctuation except _ and @
users <- gsub(regex2, "", theString1[grep(regex1, theString1, perl = T)])
users

[1] "@foobar" "@fo_o"   "@bar"

+1 很高兴知道正则表达式没有无效,尽管前瞻不会消耗字符,并且从“@”开始的匹配不应该将“(”一起获取。 = / 我很失望我不能得到一个测试环境 >_< - Jerry
1
是的,R在正则表达式方面有一些独特的细节... 在网上测试R的几个选项在这里https://dev59.com/b2vXa4cB1Zd3GeqPLal2#13716528 Ideone是我喜欢用来快速测试的工具。 - Ben
我尝试使用Ideone,但它无法找到lib stringr...否则,我就可以测试它了。感谢提供链接! - Jerry
我认为它只运行基本的 R,不安装包或进行任何类型的网络连接。 - Ben
@Ben 这是一个很好的解决方案。 然而,如果两个用户名挨在一起,例如 @John@Ben。 您的解决方案无法正常工作。 您知道如何在这种情况下使它工作吗? - zesla

2

@[a-zA-Z0-9_]{0,15}

其中:

  • @ 匹配字符 @ (大小写敏感)。

  • [a-zA-Z0-15] 匹配列表中的单个字符

  • {0,15} 量词匹配 0 到 15 次,尽可能多地匹配,并根据需要进行回退

在从混合数据集中选择 Twitter 用户名时,它可以正常工作。


1
你是否测试了 OP 的示例字符串:'@foobar Foobar! and @foo (@bar) but not foo@bar.com' - Toto
2
好的,谢谢你指出回到控制台的问题。 - suryaveer gaur

1
尝试使用负回顾后断言,以便在匹配时不消耗字符:
(?:^|(?<![-a-zA-Z0-9_]))@([A-Za-z]+[A-Za-z0-9_]+)
      ^^^

编辑:由于似乎R中的后顾断言不起作用(我在这里找到了一个地方,说后顾断言在R中可以工作,但显然不行...),尝试使用这个:

@([A-Za-z]+[A-Za-z0-9_]+)(?![A-Za-z0-9_]*\\.)

编辑:句点要转义两次

第三次编辑...:尝试开启PCRE:

str_extract_all(string=theString,perl("(?:^|(?<![-a-zA-Z0-9_]))@([A-Za-z]+[A-Za-z0-9_]+)")

1
不得不将 ?<! 更改为 ?:! 才能使其正常工作。它可以获取第一个用户名,但无法获取其他用户名,这是函数 str_extract_all() 应该执行的操作。 - Chernoff
1
当我使用<而不是:时,R会给出以下错误信息:在正则表达式(?:^|(?<![-a-zA-Z0-9_]))@([A-Za-z]+[A-Za-z0-9_]+)中,出现无效的正则表达式'(?:^|(?<![-a-zA-Z0-9_]))@([A-Za-z]+[A-Za-z0-9_]+)',原因是'无效的正则表达式'。 - Chernoff
1
@Chernoff 呃,我很确定 R 支持向后查找。如果是这样的话,根据您拥有的内容类型,您可以使用 @([A-Za-z]+[A-Za-z0-9_]+)(?![A-Za-z0-9_]*\.)。这将适用于您的示例,并检查最后一个 @ 后面是否出现了 bar. - Jerry
我提交了 str_extract_all(string=html,pattern='@([A-Za-z]+[A-Za-z0-9_]+)(?![A-Za-z0-9_]*\\.)') 但仍然没有成功:错误:无效的正则表达式'@([A-Za-z]+[A-Za-z0-9_]+)(?![A-Za-z0-9_]*\.)',原因是'无效的正则表达式'。 - Chernoff
1
要获取回顾后面,请确保在使用基本正则表达式函数时指定 perl=TRUE - Dason
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接