【问题标题】:Extracting information from textfile through regex and/or python通过正则表达式和/或 python 从文本文件中提取信息
【发布时间】:2024-01-23 16:35:01
【问题描述】:

我正在处理大量文件(价值约 4gb),它们都包含 1 到 100 个具有以下格式的条目(两个 *** 之间是一个条目):

***
Type:status
Origin: @z_rose yes
Text:  yes
URL: 
ID: 95482459084427264
Time: Mon Jul 25 08:16:06 CDT 2011
RetCount: 0
Favorite: false
MentionedEntities: 20776334 
Hashtags: 
***
***
Type:status
Origin: @aaronesilvers text
Text:  text
URL: 
ID: 95481610861953024
Time: Mon Jul 25 08:12:44 CDT 2011
RetCount: 0
Favorite: false
MentionedEntities: 2226621 
Hashtags: 
***
***
Type:status
Origin: @z_rose text
Text:  text and stuff
URL: 
ID: 95480980026040320
Time: Mon Jul 25 08:10:14 CDT 2011
RetCount: 0
Favorite: false
MentionedEntities: 20776334 
Hashtags: 
***

现在我想以某种方式将这些导入 Pandas 进行质量分析,但显然我必须将其转换为 Pandas 可以处理的格式。所以我想编写一个脚本,将上面的内容转换为 .csv,看起来像这样(用户是文件标题):

User   Type    Origin              Text  URL    ID                Time                          RetCount  Favorite  MentionedEntities  Hashtags
4012987 status  @z_rose yes         yes   Null   95482459084427264  Mon Jul 25 08:16:06 CDT 2011  0           false  20776334            Null
4012987 status  @aaronsilvers text  text Null    95481610861953024   Mon Jul 25 08:12:44 CDT 2011  0           false   2226621            Null   

(格式并不完美,但希望你能明白)

我有一些代码工作基于它通常是 12 段的信息,但遗憾的是,一些文件在某些​​字段中包含几条白线。我基本上想做的是:

fields[] =['User', 'Type', 'Origin', 'Text', 'URL', 'ID', 'Time', 'RetCount', 'Favorite', 'MentionedEntities', 'Hashtags']
starPair = 0;
User = filename;
read(file)
#Determine if the current entry has ended
if(stringRead=="***"){
    if(starPair == 0)
        starPair++;
    if(starPair == 1){
        row=row++;
        starPair = 0;
    }
}
#if string read matches column field
if(stringRead == fields[])
    while(strRead != fields[]) #until next field has been found
        #extract all characters into correct column field

但是问题出现了,一些字段可以包含字段[]中的单词。我可以先检查一个 \n 字符,这将大大减少错误条目的数量,但不会消除它们。

谁能指出我正确的方向?

提前致谢!

【问题讨论】:

  • 用户来自哪里?
  • 哦,我的错,用户是从文本文件名中提取的(所有的文本文件都是按用户 ID)。
  • 也许只是尝试用“***”分割,然后用换行符分割结果?比将它们连接到一个字符串并将其打印到文本文件中。

标签: python regex data-analysis


【解决方案1】:

您可以结合使用正则表达式和字典推导:

import regex as re, pandas as pd

rx_parts = re.compile(r'^{}$(?s:.*?)^{}$'.format(re.escape('***'), re.escape('***')), re.MULTILINE)
rx_entry = re.compile(r'^(?P<key>\w+):[ ]*(?P<value>.+)$', re.MULTILINE)

result = ({m.group('key'): m.group('value') 
            for m in rx_entry.finditer(part.group(0))}
            for part in rx_parts.finditer(your_string_here))

df = pd.DataFrame(result)
print(df)

产量

  Favorite Hashtags                 ID MentionedEntities               Origin  \
0    false           95482459084427264         20776334           @z_rose yes   
1    false           95481610861953024          2226621   @aaronesilvers text   
2    false           95480980026040320         20776334          @z_rose text   

  RetCount            Text                          Time    Type URL  
0        0             yes  Mon Jul 25 08:16:06 CDT 2011  status      
1        0            text  Mon Jul 25 08:12:44 CDT 2011  status      
2        0  text and stuff  Mon Jul 25 08:10:14 CDT 2011  status      


解释:
  1. 将字符串分成不同的部分,两边用***包围
  2. 在每一行中查找键值对
  3. 将所有对放在一个字典中

我们最终得到了一个字典生成器,然后我们将其输入到pandas

提示:

代码没有经过大量数据的测试,尤其是4gb。此外,您需要更新的 regex 模块才能使表达式工作。

【讨论】:

  • 我的笔记本电池工作不正常,希望能在周末进行测试!无论如何感谢您的回答!
  • 不得不订购一块新电池,我的笔记本电脑终于又能正常工作了,对于延迟回复表示歉意。我收到以下错误:A:\Programmas\Anaconda\lib\sre_parse.py in _parse(source, state) 760 break 761 if char not in FLAGS: --&gt; 762 raise source.error("unknown flag", len(char)) 763 verbose = state.flags &amp; SRE_FLAG_VERBOSE 764 continue 而且我似乎不知道如何解决它。
【解决方案2】:

你的代码/伪代码看起来不像 python,但是因为你有 python 标签,所以我会这样做。首先,将文件读入字符串,然后遍历每个字段并制作正则表达式以查找其后面的值,将结果推送到二维列表中,然后将该二维列表输出为 CSV。此外,您的 CSV 看起来更像 TSV(制表符分隔而不是逗号分隔)。

import re
import csv

filename='4012987'
User=filename

# read your file into a string
with open(filename, 'r') as myfile:
    data=myfile.read()

fields =['Type', 'Origin', 'Text', 'URL', 'ID', 'Time', 'RetCount', 'Favorite', 'MentionedEntities', 'Hashtags']
csvTemplate = [['User','Type', 'Origin', 'Text', 'URL', 'ID', 'Time', 'RetCount', 'Favorite', 'MentionedEntities', 'Hashtags']]

# for each field use regex to get the entry
for n,field in enumerate(fields):
  matches = re.findall(field+':\s?([^\n]*)\n+', data)
  # this should run only the first time to fill your 2d list with the right amount of lists
  while len(csvTemplate)<=len(matches):
    csvTemplate.append([None]*(len(fields)+1)) # Null isn't a python reserved word
  for e,m in enumerate(matches):
    if m != '':
      csvTemplate[e+1][n+1]=m.strip()
# set the User column
for i in range(1,len(csvTemplate)):
  csvTemplate[i][0] = User
# output to csv....if you want tsv look at https://*.com/a/29896136/3462319
with open("output.csv", "wb") as f:
    writer = csv.writer(f)
    writer.writerows(csvTemplate)

【讨论】:

  • 我的笔记本电池工作不正常,希望能在周末进行测试!无论如何感谢您的回答!
  • 您好,我的笔记本电脑现在修好了,对于延迟回复表示歉意。我不得不将“wb”更改为“w”,否则它不会运行。谢谢!
  • 只是想跟进它似乎运行良好。最后,我实际上有将近 20gb 的数据,而且我测试过的所有样本都非常完美。非常感谢!