#Cargamos librerias necesarias
import sqlite3
import json
from datetime import datetime
import time
#De todos los meses disponibles en los datos del torrent de de reddit elijo marzo de 2015
timeframe = '2015-03'
sql_transaction = []
start_row = 0
cleanup = 1000000
#vamos a almacenar los datos en un una BBDD sqlLite
connection = sqlite3.connect('{}.db'.format(timeframe))
c = connection.cursor()
#Nos creamos una función para crear la tabla donde guardamos los campos que nos interesan del #JSON. En este caso son:
def create_table():
c.execute("CREATE TABLE IF NOT EXISTS parent_reply(parent_id TEXT PRIMARY KEY, comment_id TEXT UNIQUE, parent TEXT, comment TEXT, subreddit TEXT, unix INT, score INT)")
#Función para formatear los datos que vamos leyendo
def format_data(data):
data = data.replace('\n',' newlinechar ').replace('\r',' newlinechar ').replace('"',"'")
return data
# Esta función se utiliza para crear sentencias de inserción y confirmarlas en grupos
# en lugar de hacer que inserte uno a uno
def transaction_bldr(sql):
global sql_transaction
sql_transaction.append(sql)
if len(sql_transaction) > 1000:
c.execute('BEGIN TRANSACTION')
for s in sql_transaction:
try:
c.execute(s)
except:
pass
connection.commit()
sql_transaction = []
#función que actualiza el comentarios en nuestra BBDD sqlLite
def sql_insert_replace_comment(commentid,parentid,parent,comment,subreddit,time,score):
try:
sql = """UPDATE parent_reply SET parent_id = ?, comment_id = ?, parent = ?, comment = ?, subreddit = ?, unix = ?, score = ? WHERE parent_id =?;""".format(parentid, commentid, parent, comment, subreddit, int(time), score, parentid)
transaction_bldr(sql)
except Exception as e:
print('s0 insertion',str(e))
#Funcion que guarda en BBDD un comentario que tiene padre
def sql_insert_has_parent(commentid,parentid,parent,comment,subreddit,time,score):
try:
sql = """INSERT INTO parent_reply (parent_id, comment_id, parent, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}","{}",{},{});""".format(parentid, commentid, parent, comment, subreddit, int(time), score)
transaction_bldr(sql)
except Exception as e:
print('s0 insertion',str(e))
#Funcion que guarda en BBDD un comentario que no tiene padre
def sql_insert_no_parent(commentid,parentid,comment,subreddit,time,score):
try:
sql = """INSERT INTO parent_reply (parent_id, comment_id, comment, subreddit, unix, score) VALUES ("{}","{}","{}","{}",{},{});""".format(parentid, commentid, comment, subreddit, int(time), score)
transaction_bldr(sql)
except Exception as e:
print('s0 insertion',str(e))
#Solo guardamos los comentarios cuyo tamaño sea válido para el entrenamiento
def acceptable(data):
if len(data.split(' ')) > 1000 or len(data) < 1:
return False
elif len(data) > 32000:
return False
elif data == '[deleted]':
return False
elif data == '[removed]':
return False
else:
return True
#Función que encuentra el padre de un comentario dado
def find_parent(pid):
try:
sql = "SELECT comment FROM parent_reply WHERE comment_id = '{}' LIMIT 1".format(pid)
c.execute(sql)
result = c.fetchone()
if result != None:
return result[0]
else: return False
except Exception as e:
#print(str(e))
return False
#Función que nos da la puntuación de un comentario dado
def find_existing_score(pid):
try:
sql = "SELECT score FROM parent_reply WHERE parent_id = '{}' LIMIT 1".format(pid)
c.execute(sql)
result = c.fetchone()
if result != None:
return result[0]
else: return False
except Exception as e:
#print(str(e))
return False
if __name__ == '__main__':
create_table() #Empezamos creando la tabla sobre la que almacenar los datos
row_counter = 0 #Contador para ver en que parte del archivo estamos.Va contando las filas
paired_rows = 0 #Contador que nos dice las filas que están emparejas.Pregunta con respuesta
#Abrimos la ubicación del archivo que nos iteresa y vamos lyendo filas
with open('D:/reddit/RC_{}'.format(timeframe), buffering=1000) as f:
for row in f:
#print(row)
#time.sleep(555)
row_counter += 1
#vamos obtiendo los datos quqe nos interesan de cada fila
if row_counter > start_row:
try:
row = json.loads(row)
parent_id = row['parent_id'].split('_')[1]
body = format_data(row['body'])
created_utc = row['created_utc']
score = row['score']
comment_id = row['id']
subreddit = row['subreddit']
#Todos los comentarios inicialmente no tendrán un padre.
#Sin embargo, a medida que avanzamos en el documento, encontraremos
#comentarios que tienen padres que tenemos en nuestra base de datos.
#Cuando esto sucede, queremos agregar este comentario al padre existente.
parent_data = find_parent(parent_id)
existing_comment_score = find_existing_score(parent_id)
#Si existe un comentario asociado al padre con mejor puntuación reemplazamos
#el comentario existente.
#En el caso que el comentario no tenga padre se inserta
if existing_comment_score:
if score > existing_comment_score:
if acceptable(body):#validamos el tamaño
sql_insert_replace_comment(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)
else:
if acceptable(body):
if parent_data:
if score >= 2:#solo tratamos comentarios con más de dos votos
sql_insert_has_parent(comment_id,parent_id,parent_data,body,subreddit,created_utc,score)
paired_rows += 1
else:
sql_insert_no_parent(comment_id,parent_id,body,subreddit,created_utc,score)
except Exception as e:
print(str(e))
#Muestro por pantalla cada 100000 filas
if row_counter % 100000 == 0:
print('Total Rows Read: {}, Paired Rows: {}, Time: {}'.format(row_counter, paired_rows, str(datetime.now())))
#Finalmente borrmos los comentarios que no tengan padre cada 100000 lineas #procesadas
if row_counter > start_row:
if row_counter % cleanup == 0:
print("Cleanin up!")
sql = "DELETE FROM parent_reply WHERE parent IS NULL"
c.execute(sql)
connection.commit()
c.execute("VACUUM")
connection.commit()