[ Foro de Python ]
Estoy utilizando GNU/LINUX: Xubuntu 14.04
Python 2.7.9
MySQL 5.5.43
E creado un Script en python el cual es un crawler y su función debe ser buscar e indexar todas las url's de una dirección semilla. También este script es capaz de crear tablas en una BD previamente creada. Lo que hasta hoy día no e podido es realizar la inserción de los datos que obtengo de la url semilla y que estas sean guardadas en sus respectivas tablas dentro de la BD creada tengo todo correcto según yo espero puedan ayudarme les dejo el codigo:
# -*- coding: utf-8 *-*
# lizsags S.R.L de C.V
# sags@Lizsags.com.mx
# 2 de Mayo, 2015
import urllib, re, os, MySQLdb, string, urlparse, htmllib, time
class dividir_texto:
# Esta clase es para dividir el texto en una lista de palabras "limpias" de menos de 15 caracteres
# de longitud lo cual es adecuado para la inclusion en una tabla de base de datos en una
# busqueda de texto completo
def __init__(self, text):
self.__text = text
self.__stop_word_list = ("all", "an", "and", "any", "as", "at", "be", "for", "from", "if", "in", "is", "it", "may", "name", "no", "not", "of", "on", "or", "telstra", "that", "the", "these", "this", "to", "use", "when", "with", "which")
def get_split_text (self):
reo = re.compile(r"""
(\w+) # Incluyendo caracteres alfanumericos
""", re.VERBOSE|re.IGNORECASE)
word_list = reo.findall(self.__text)
result_list = []
for word in word_list:
if word not in result_list and len(word) > 1 and len(word) < 15 and word not in self.__stop_word_list:
result_list.append(word)
return result_list
class mi_analizador(htmllib.HTMLParser):
# Esta clase la utilizo para analizar el titulo y el texto que esta fuera de las etiquietas
# <html> para una explicacion mas amplia sobre el funcionamiento consultar la documentacion
# de Python para el modulo htmllib
def __init__(self):
import formatter
self.formatter = formatter.NullFormatter()
htmllib.HTMLParser.__init__(self, self.formatter)
self.extracted_text = ""
self.title = ""
def handle_starttag(self, tag, method, attrs):
if (tag == "title"):
self.flag_collect_title = 1
def handle_endtag(self, tag, method):
if (tag == "title"):
self.flag_collect_title = 0
def start_title(self, attrs):
print "en el inicio del titulo"
self.flag_collect_title = 1
def end_title(self, attrs):
print "en el final del titulo"
self.flag_collect_title = 0
def handle_data(self, data):
# Algunos datos "basura" se consiguen, incluso cuando usamos la condicion
# if len(data)> 10. los Strings de lineas nuevas puede ser y no parece afectar
# el rendimiento.
if len(data) > 6:
if self.flag_collect_title:
self.title = self.title + data
else:
self.extracted_text = self.extracted_text + " " + data
def get_text(self):
result = self.extracted_text
self.extracted_text = ""
return result
def get_title(self):
result = self.title
self.title = ""
return result
# ========================================================
# Funciones de ayuda para el sistema principal
# ========================================================
def create_WORDS_table():
conn = MySQLdb.connect("localhost","root","sags","lizsags_db");
cursor = conn.cursor()
# Interesa solo guardar palabras pequenas, lo mismo limito el tamano del campo word a 15
sql = """CREATE TABLE WORDS (
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
word VARCHAR(15) NOT NULL,
INDEX (word)
);"""
result = cursor.execute(sql)
conn.close()
def create_WORDS_X_URL_table():
conn = MySQLdb.connect("localhost","root","sags","lizsags_db");
cursor = conn.cursor()
sql = """CREATE TABLE WORDS_X_URL (
word_id INT NOT NULL,
url_id INT NOT NULL,
INDEX (word_id),
INDEX (url_id)
);"""
result = cursor.execute(sql)
conn.close()
def create_URLS_table():
conn = MySQLdb.connect("localhost","root","sags","lizsags_db");
cursor = conn.cursor()
sql = """CREATE TABLE URLS (
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
url VARCHAR(255) NOT NULL,
title VARCHAR(255),
INDEX (url)
);"""
result = cursor.execute(sql)
conn.close()
def get_urls_list():
# Esta funcion regresa una lista de direcciones url calificadas para todas las paginas que queremos indexar
# La direccion a la cual estaremos analizando se encuentra en el os.path.join alojado en el objeto url_list_path
result_list = []
url_list_path = os.path.join("http://www.taringa.net/")
url_object = urllib.urlopen(url_list_path)
lines = url_object.readlines()
reo = re.compile(r"""
\"
(?P<url>
(\S*?)
\.html)
""", re.VERBOSE|re.IGNORECASE|re.DOTALL)
line_count = 0
for line in lines:
line_count = line_count + 1
# saltamos las primeras 10 lineas como estas incluyen <href> que no queremos
if line_count > 10:
result = reo.search(line)
if result:
url = result.group('url')
full_url = urlparse.urljoin(url_list_path, url)
result_list.append(full_url)
return result_list
def create_FTS_index(lista_url):
try:
create_WORDS_table()
except Exception:
print "\nOcurrio un inconveniente mientras se creaba la tabla WORDS. Probablemente ya exista la tabla."
try:
create_URLS_table()
except Exception:
print "\nOcurrio un inconveniente mientras se creaba la tabla URLS. Probablemente ya exista la tabla."
try:
create_WORDS_X_URL_table()
except Exception:
print "\nOcurrio un inconveniente mientras se creaba la tabla WORDS_X_URL. Probablemente ya exista la tabla.\n\n\n"
conn = MySQLdb.connect("localhost","root","sags","lizsags_db")
cursor = conn.cursor()
known_words_list = []
known_words_dict = {}
for url in lista_url:
print "procesando la url: ", url
try:
url_object = urllib.urlopen(url)
text = url_object.read()
p = mi_analizador()
p.feed(text)
p.close()
parsed_text = p.get_text()
title = p.get_title()
if title == "":
title = "Sin titulo"
# Remplazar la comilla simple con la entidad html correspondiente
title = string.replace(title, "href", "'")
print title
except:
print "No se puede abrir la siguiente Url: %s" % url
continue
# Crear entradas para la url en la tabla URLS, pero antes se debera anadir las diagonales
# antes de cada \
escaped_url = string.replace(url, "\\", "\\\\")
sql = """INSERT INTO URLS (url, title) VALUES ('"""
sql = sql + escaped_url + """' , '""" + title + """');"""
cursor.execute(sql)
ts = dividir_texto(parsed_text)
word_list = ts.get_split_text()
for word in word_list:
# Convierte todas las palabras minusculas, asi tendremos casos de coincidencia insensibles
word = string.lower(word)
# Ignora palabras de mas de 14 caracteres
if word not in known_words_list:
known_words_list.append(word)
if not known_words_dict.has_key(word):
known_words_dict[word] = 0
# Asumimos que word no esta en la tabla WORDS (esto supone que estamos insertando en la tabla
# desde cero). Asi que anadimos a la tabla
sql = """INSERT INTO WORDS (word) VALUES ('"""
sql = sql + word + """');"""
cursor.execute(sql)
# como aun no tenemos una entrada para word dentro de la tabla WORDS, esto no es una entrada
# para la combinacion word/url en la tabla WORDS_X_URL y la anadimos
sql = """SELECT id FROM WORDS WHERE word = '"""
sql = sql + word + """';"""
cursor.execute(sql)
result = cursor.fetchone()
word_id = result[0]
# Guardar nuestra cache aqui
known_words_dict[word] = word_id
sql = """SELECT id FROM URLS WHERE url = '"""
sql = sql + escaped_url + """';"""
cursor.execute(sql)
result = cursor.fetchone()
url_id = result[0]
sql = """INSERT INTO WORDS_X_URL VALUES ("""
sql = sql + "%s" % (word_id)
sql = sql + """, """
sql = sql + "%s" % (url_id)
sql = sql + """);"""
cursor.execute(sql)
else:
# Este word ya esta en la tabla WORDS. Existen entradas para WORDS_X_URL para la
# combinacion word/url?
# Primero, mantenemos word_id
if known_words_dict.has_key(word):
word_id = known_words_dict[word]
else:
print "Recuperando word_id con SQL"
sql = """SELECT id FROM WORDS WHERE word = '"""
sql = sql + word + """';"""
cursor.execute(sql)
result = cursor.fetchone()
word_id = result[0]
# Ahora sostenemos url_id
sql = """SELECT id FROM URLS WHERE url = '"""
sql = sql + escaped_url + """';"""
cursor.execute(sql)
result = cursor.fetchone()
url_id = result[0]
sql = """SELECT * FROM WORDS_X_URL WHERE word_id = """
sql = sql + "%s" % (word_id)
sql = sql + """ AND url_id = """
sql = sql + "%s" % (url_id)
cursor.execute(sql)
result = cursor.fetchall()
if len(result) == 0:
# No existian entradas, asi que las agregamos
sql = """INSERT INTO WORDS_X_URL VALUES ("""
sql = sql + "%s" % (word_id)
sql = sql + """, """
sql = sql + "%s" % (url_id)
sql = sql + """);"""
cursor.execute(sql)
conn.close()
print "\nFinalizo la creacion del indexado FTS"
def main():
inicio_de_tiempo = time.time()
lista_url = get_urls_list()
for url in lista_url:
print url
lista_temp = lista_url
for url in lista_temp:
print url
num_a_procesar = len(lista_temp)
create_FTS_index(lista_temp)
print "\nFinalizo la creacion del indexado en Lizsags"
tiempo_final = time.time()
tiempo_transcurrido = tiempo_final - inicio_de_tiempo
print "\nTomo %d segundos indexar %d paginas. Tiempo promedio por pagina= %d segundos\n\n\n" % (tiempo_transcurrido, num_a_procesar, tiempo_transcurrido/num_a_procesar)
main()
Ese código es exageradamente largo para una consulta. Intenta reducir el problema a un fragmento más pequeño (lo ideal sería que fuera el fragmento más pequeño posible que aún se comportase de forma errónea).
¿Por qué no creas un programa muy simple que cree la base de datos, la tabla e inserte datos prefijados en ella?
Como podría hacer eso todo este codigo lo recopilé de cursos y libros en la web y los adapté según mis necesidades pero aun no logro que se pueda insertar los datos
Insisto: extrae el fragmento más pequeño posible.
Lo malo de copiar y pegar fragmentos de Internet es que puedes llegar a no entender lo que estás haciendo, y puede haber incompatibilidades entre unos fragmentos y otros.
Por eso, si tu problema actual se resume a "no consigo insertar", busca (o crea, o extrae de ese programa) un fragmento de código que inserte datos en una base de datos, comprueba si funciona y soluciónalo en caso de que no sea así.
Cuando funcione, añades otro pequeño fragmento que le dé otra posibilidad adicional, y te aseguras de que funciona correctamente, y así sucesivamente.
(No se puede continuar esta discusión porque tiene más de dos meses de antigüedad. Si tienes dudas parecidas, abre un nuevo hilo.)