...
[iramuteq] / parse_dmi.py
1 #!/bin/env python
2 # -*- coding: utf-8 -*-
3 #Author: Pierre Ratinaud
4 #Copyright (c) 2014, Pierre Ratinaud
5 #License: GNU GPL
6
7 import csv, codecs, cStringIO
8 import itertools
9 from parse_factiva_xml import PrefImport
10 import wx
11 import os
12 from functions import BugReport
13
14 #filein = '/home/pierre/workspace/iramuteq/dev/dmi-tcat/travail_dmi.csv'
15 #fileout = '/home/pierre/workspace/iramuteq/dev/dmi-tcat/corpus.txt'
16
17 class UTF8Recoder:
18     """
19     Iterator that reads an encoded stream and reencodes the input to UTF-8
20     """
21     def __init__(self, f, encoding):
22         self.reader = codecs.getreader(encoding)(f)
23
24     def __iter__(self):
25         return self
26
27     def next(self):
28         return self.reader.next().encode("utf-8")
29
30 class UnicodeReader:
31     """
32     A CSV reader which will iterate over lines in the CSV file "f",
33     which is encoded in the given encoding.
34     """
35
36     def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
37         f = UTF8Recoder(f, encoding)
38         self.reader = csv.reader(f, dialect=dialect, **kwds)
39
40     def next(self):
41         row = self.reader.next()
42         return [unicode(s, "utf-8") for s in row]
43
44     def __iter__(self):
45         return self
46
47 class UnicodeWriter:
48     """
49     A CSV writer which will write rows to CSV file "f",
50     which is encoded in the given encoding.
51     """
52
53     def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
54         # Redirect output to a queue
55         self.queue = cStringIO.StringIO()
56         self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
57         self.stream = f
58         self.encoder = codecs.getincrementalencoder(encoding)()
59
60     def writerow(self, row):
61         self.writer.writerow([s.encode("utf-8") for s in row])
62         # Fetch UTF-8 output from the queue ...
63         data = self.queue.getvalue()
64         data = data.decode("utf-8")
65         # ... and reencode it into the target encoding
66         data = self.encoder.encode(data)
67         # write to the target stream
68         self.stream.write(data)
69         # empty queue
70         self.queue.truncate(0)
71
72     def writerows(self, rows):
73         for row in rows:
74             self.writerow(row)
75
76 class ParseDMI :
77     def __init__(self, filein, fileout, encodeout ='utf8', onlyrt = True, cleanurl = True, cleanRT = True, cleanAt = True, lang= 'es'):
78         self.outf = open(fileout, 'w')
79         self.encodeout = encodeout
80         with open(filein, 'rb') as f:
81             reader = UnicodeReader(f)
82             linenb = 0
83             for row in reader:
84                 if linenb == 0 :
85                     first = row
86                     self.create_dateid = first.index('created_at')
87                     textid = first.index('text')
88                     langid = first.index('lang')
89                 else :
90                     text = row[textid]
91                     text = self.washtweet(text)
92                     isrt = self.isRT(text)
93                     if cleanurl :
94                         text = self.cleanurl(text)
95                     if cleanRT :
96                         text = self.cleanRT(text)
97                     if cleanAt :
98                         text = self.cleanAt(text)
99                     if onlyrt and not isrt :
100                         if lang == 'all' :
101                             self.write_tweet(row, text)
102                         elif row[langid] == lang :
103                             self.write_tweet(row, text)
104                     if not onlyrt :
105                         if lang == 'all' :
106                             self.write_tweet(row, text)
107                         elif row[langid] == lang :
108                             self.write_tweet(row, text)
109                 linenb += 1
110         self.outf.close()
111     
112     def write_tweet(self, row, text):
113         meta = self.makemetadata(row, {'date' : self.create_dateid})
114         self.outf.write('\n'.join([meta, text, '']).encode(self.encodeout))
115     
116     def makemetadata(self, row, parametres = {}):
117         line = [u'****']
118         for val in parametres :
119             if val == 'date' :
120                 line.append('_'.join([u'*date', row[parametres[val]].split()[0]]))
121             else :
122                 line.append('_'.join([val,row[parametres[val]]]))
123         return ' '.join(line)
124     
125     def washtweet(self, text) :
126         text = text.replace(u'RT“', u'RT ')
127         text = text.replace(u'*', ' ')
128         for val in u'”«»“"' :
129             text = text.replace(val, ' " ')
130         text.strip()
131         return text
132
133     def isRT(self, tweet):
134         if tweet.startswith('RT ') :
135             return True
136         else :
137             return False
138
139     def cleanurl(self, tweet) :
140         return ' '.join([word for word in tweet.split() if not word.startswith('http')])
141
142     def cleanAt(self, tweet) :
143         return ' '.join([word for word in tweet.split() if not word.startswith('@')])
144
145     def cleanRT(self, text) :
146         text = ''.join([' ',text, ' '])
147         text.replace('rt','_rt_')
148         text = text.replace('RT', '_rt_')
149         text.strip()
150         #tweet = text.split()
151         #tovire = [[i, i+1] for i, word in enumerate(tweet) if word == 'RT' and i!=len(tweet) - 1]
152         #tovire = itertools.chain(*tovire)
153         #text = ' '.join([word for i, word in enumerate(tweet) if i not in tovire])
154         return text
155
156 class ImportDMI :
157     def __init__(self, parent, parametres):
158         self.ira = parent
159         self.parametres = parametres
160         self.parse()
161     
162     def parse(self):
163         self.dial =  PrefImport(self.ira, methode='dmi')
164         val = self.dial.ShowModal()
165         if val == wx.ID_OK :
166             csvfile = self.dial.dbb.GetValue()
167             corp_out = self.dial.fbb.GetValue()
168             nort = self.dial.paneldmi.check_removeR_rt.GetValue()
169             remove_url = self.dial.paneldmi.check_remove_url.GetValue()
170             remove_mention = self.dial.paneldmi.check_remove_mention.GetValue()
171             remove_rt_in_tweets = self.dial.paneldmi.check_remove_rt_in_tweets.GetValue()
172             self.dial.Destroy()
173             busy = wx.BusyInfo(_("Please wait...").decode('utf8'))
174             wx.SafeYield()
175             try :
176                 ParseDMI(csvfile, corp_out, 'utf8', onlyrt=nort, cleanurl=remove_url, cleanAt=remove_mention, cleanRT=remove_rt_in_tweets)
177                 del busy
178                 msg = '\n'.join([_(u"Corpus created :").decode('utf8'), corp_out, _(u"Do you want to open it in IRaMuTeQ ?").decode('utf8')])
179                 dlg = wx.MessageDialog(self.ira, msg, _(u'Information').decode('utf8'), wx.YES_NO | wx.ICON_INFORMATION | wx.STAY_ON_TOP)
180                 dlg.CenterOnParent()
181                 val = dlg.ShowModal()
182                 if val == wx.ID_YES :
183                     dlg.Destroy()
184                     self.ira.filename = os.path.abspath(corp_out)
185                     self.ira.OpenText()
186                 else :
187                     dlg.Destroy()
188             except :
189                 del busy
190                 BugReport(self.ira)
191         else :
192             self.dial.Destroy()       
193         
194 #ParseDMI(filein, fileout, 'utf8')