用Python预处理4亿条推文 - 速度更快

时间:2012-01-06 20:29:31

标签: python twitter

我有4亿条推文(实际上我认为它几乎像450但不记得),形式如下:

T    "timestamp"
U    "username"
W    "actual tweet"

我想最初以“username \ t tweet”的形式将它们写入文件,然后加载到数据库中。问题是在加载到db之前,我需要做一些事情: 1.预处理推文以删除RT @ [名称]和网址 2.从“http://twitter.com/username”中取出用户名。

我正在使用python,这是代码。请让我知道如何更快地实现这一目标:)

'''The aim is  to take all the tweets of a user and store them in a table.  Do this for all the users and then lets see what we can do with it 
   What you wanna do is that you want to get enough information about a user so that you can profile them better. So , lets get started 
'''
def regexSub(line):
    line = re.sub(regRT,'',line)
    line = re.sub(regAt,'',line)
    line = line.lstrip(' ')
    line = re.sub(regHttp,'',line)
    return line
def userName(line):
    return line.split('http://twitter.com/')[1]


import sys,os,itertools,re
data = open(sys.argv[1],'r')
processed = open(sys.argv[2],'w')
global regRT 
regRT = 'RT'
global regHttp 
regHttp = re.compile('(http://)[a-zA-Z0-9]*.[a-zA-Z0-9/]*(.[a-zA-Z0-9]*)?')
global regAt 
regAt = re.compile('@([a-zA-Z0-9]*[*_/&%#@$]*)*[a-zA-Z0-9]*')

for line1,line2,line3 in itertools.izip_longest(*[data]*3):
    line1 = line1.split('\t')[1]
    line2 = line2.split('\t')[1]
    line3 = line3.split('\t')[1]

    #print 'line1',line1
    #print 'line2=',line2
    #print 'line3=',line3
    #print 'line3 before preprocessing',line3
    try:
        tweet=regexSub(line3)
        user = userName(line2)
    except:
        print 'Line2 is ',line2
        print 'Line3 is',line3

    #print 'line3 after processig',line3
    processed.write(user.strip("\n")+"\t"+tweet)

我按以下方式运行代码:

python -m cProfile -o profile_dump TwitterScripts/Preprocessing.py DATA/Twitter/t082.txt DATA/Twitter/preprocessed083.txt

这是我得到的输出:(警告:它相当大,我没有过滤掉小值,想一想,它们也可能有一些意义)

Sat Jan  7 03:28:51 2012    profile_dump

         3040835560 function calls (3040835523 primitive calls) in 2500.613 CPU seconds

   Ordered by: call count

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
528840744  166.402    0.000  166.402    0.000 {method 'split' of 'str' objects}
396630560   81.300    0.000   81.300    0.000 {method 'get' of 'dict' objects}
396630560  326.349    0.000  439.737    0.000 /usr/lib64/python2.7/re.py:229(_compile)
396630558  255.662    0.000 1297.705    0.000 /usr/lib64/python2.7/re.py:144(sub)
396630558  602.307    0.000  602.307    0.000 {built-in method sub}
264420442   32.087    0.000   32.087    0.000 {isinstance}
132210186   34.700    0.000   34.700    0.000 {method 'lstrip' of 'str' objects}
132210186   27.296    0.000   27.296    0.000 {method 'strip' of 'str' objects}
132210186  181.287    0.000 1513.691    0.000 TwitterScripts/Preprocessing.py:4(regexSub)
132210186   79.950    0.000   79.950    0.000 {method 'write' of 'file' objects}
132210186   55.900    0.000  113.960    0.000 TwitterScripts/Preprocessing.py:10(userName)
  313/304    0.000    0.000    0.000    0.000 {len}

删除那些非常低的(如1,3等等)

请告诉我可以做出哪些其他更改。谢谢 !

5 个答案:

答案 0 :(得分:7)

这是multiprocessing的用途。

您有一个可以分解为大量小步骤的管道。每个步骤都是Process,它用于从管道获取项目,进行小的转换并将中间结果放入下一个管道。

你将有Process一次读取原始文件三行,并将三行放入管道。就是这样。

你将有Process从管道中获取(T,U,W)三元组,清理用户线,并将其放入下一个管道。

等等。

不要构建太多的步骤来开始。读 - 转换 - 写是一个很好的开始,以确保您理解multiprocessing模块。之后,这是一项实证研究,以找出最佳的处理步骤组合。

当你解决这个问题时,它会产生许多通信顺序进程,这些进程会消耗你所有的CPU资源,但会相对快速地处理文件。

通常,同时工作的更多进程更快。由于操作系统开销和内存限制,您最终会达到限制。

答案 1 :(得分:3)

在通过分析器运行之前,很难知道需要更改的内容。但是,我建议在创建和运行正则表达式的地方发生最可能的减速。

由于您的文件遵循特定格式,因此使用lex + yacc组合可能会显着提高速度。如果你使用python lex+yacc,你将不会看到速度增加,但你不需要使用c代码。

如果这看起来有点矫枉过正,请在开始循环之前尝试compiling正则表达式。您还可以拥有由独立工作线程/进程运行的文件块。

同样,分析将揭示实际导致瓶颈的原因。首先找出它,然后看看这些选项是否能解决问题。

答案 2 :(得分:3)

str.lstrip可能没有按照你的预期行事:

>>> 'http://twitter.com/twitty'.lstrip('http://twitter.com/')
'y'

来自文档:

S.lstrip([chars]) -> string or unicode

Return a copy of the string S with leading whitespace removed.
If chars is given and not None, remove characters in chars instead.
If chars is unicode, S will be converted to unicode before stripping

答案 3 :(得分:1)

查看分析信息,您在regexSub上花了很多时间。您可能会发现可以将正则表达式合并为一个,并进行一次替换。

类似的东西:

regAll = re.compile(r'RT|(^[ \t]+)|((http://)[a-zA-Z0-9]*.[a-zA-Z0-9/]*(.[a-zA-Z0-9]*)?)|...')

(这样做的目的不仅是用re.sub替换你正在做的所有事情,而且还用lstrip替换你正在做的所有事情)。我用......结束了模式:你必须自己填写细节。

然后用以下代码替换regexSub:

line = regAll.sub(line)

当然,只有分析会显示这是否更快,但我希望它会生成更少的中间字符串。

答案 4 :(得分:0)

为了预处理推文,您可以使用 tweetprep Python 库。

它还可以用于将推文翻译成任何其他语言。

图书馆链接: https://pypi.org/project/tweetprep/

安装:

pip install tweetprep

用法:

from tweetprep import preprocess
#from tweetprep import lang_translator

tweet = "#COVID-19 is the worst pandemic @2020!! :,("
# get translated tweet
lang="es"
print(preprocess.lang_translator.translate(tweet,dest=lang).text)

# Get processed version of tweet
print(preprocess.clean(tweet))

输出:

# COVID-19 es la peor pandemia @ 2020!! :,(
covid19 is the worst pandemic crying smiley