Análisis de la mesa de Wikipedia con Python -- python campo con python-3.x campo con parsing campo con web-scraping campo con wikipedia camp codereview Relacionados El problema

Parsing Wikipedia table with Python


8
vote

problema

Español

Soy nuevo en Python y recientemente comenzó a explorar el gateador web. El código a continuación analiza el s & amp; p 500 Lista de la página Wikipedia y escribe los datos de un Tabla específica en una base de datos.

Si bien este script se codifica y ciertamente estaría interesado en algunos pensamientos sobre la realización de la misma tarea de una manera ligeramente más genérica (tal vez con Option7 ), esta no es mi principal preocupación. Lo que realmente me pregunté era si hay una forma menos verbosa o más "pythonic" de hacerlo.

  Option8  
Original en ingles

I am new to Python and recently started exploring web crawling. The code below parses the S&P 500 List Wikipedia page and writes the data of a specific table into a database.

While this script is hardcoded and I would certainly be interested in some thoughts on performing the same task in a slightly more generic way (perhaps with beautifulsoup), this is not my primary concern. What I really wondered was if there is a less verbose or more "pythonic" way of doing it.

import urllib.request import re import pymysql  # Open Website and get only the table on the page with the relevant data. In this hardcoded case  table = urllib.request.urlopen("https://en.wikipedia.org/wiki/List_of_S%26P_500_companies#S.26P_500_Component_Stocks").read().decode("utf-8") table = table.split("<table")[1] table = table.split("\n")  # Define regex used for parsing and initialise list containers tick_ident_nasdaq = 'href=\"http:\/\/www\.nasdaq\.com\/symbol\/' tick_ident_nyse = 'href=\"https:\/\/www.nyse.com\/quote\/' name_grab = '\">(.+)<\/a></td>' cigs_grab = '^<td>(.+)</td>'  ticker, exchange, names, cigs, cigs_sub = ( [] for i in range(5)) match = False             # Parse HTML output and write relevant td data to lists.  # The list is "hardcoded", meaning after each match of either NASDAQ or NYSE ident,  # the matching <td> as well as the next, the fourth and fifth <td> after that one get parsed.    for i in range(len(table)):     if bool(re.search(pattern = tick_ident_nasdaq, string = table[i])):         ticker.append(re.search(pattern = name_grab, string = table[i]).group(1))         exchange.append("NASDAQ")         match = True      elif bool(re.search(pattern = tick_ident_nyse, string = table[i])):         ticker.append(re.search(pattern = name_grab, string = table[i]).group(1))         exchange.append("NYSE")         match = True      if match == True:         names.append(re.search(pattern = name_grab, string = table[i + 1]).group(1))         names[-1] = re.sub(pattern = "&amp;", repl = "&", string = names[-1])         cigs.append(re.search(pattern = cigs_grab, string = table[i + 3]).group(1))         cigs[-1] = re.sub(pattern = "&amp;", repl = "&", string = cigs[-1])         cigs_sub.append(re.search(pattern = cigs_grab, string = table[i + 4]).group(1))         cigs_sub[-1] = re.sub(pattern = "&amp;", repl = "&", string = cigs_sub[-1])         match = False  # Format Data in tuple format for database export company_data = zip(ticker, exchange, names, cigs, cigs_sub)  # Establish database connection, empty companies table and rewrite list data to table     try:     conn = pymysql.connect(host = "localhost", user = "root", passwd = "pw", db = "db", charset = "utf8", autocommit = True, cursorclass=pymysql.cursors.DictCursor)     cur = conn.cursor()     cur.execute("DELETE FROM companies")     cur.executemany("INSERT INTO companies (tickersymbol, exchange, name, cigs, cigs_sub) VALUES (\"%s\", \"%s\", \"%s\", \"%s\", \"%s\")", (company_data))    finally:     cur.close()     conn.close() 
              

Lista de respuestas

11
 
vote
vote
La mejor respuesta
 

la herramienta adecuada

Como ha dicho, no está utilizando la herramienta adecuada para esta tarea: usted No se puede analizar HTML con regexps .

Un mejor enfoque sería usar un analizador ya existente como BeautifulSoup.

un contenedor más simple

En este momento, está poniendo datos en múltiples listas para cerrarlas todo al final. Puede ser una técnica muy agradable, pero en nuestro caso, usted pone en diferentes contenedores cosas que realmente pertenecen juntas. Además, tiene el riesgo de agregar demasiados elementos en una lista y tener información con cremallera con información que debe estar en una fila diferente. Una opción más fácil es tener una lista única donde cada elemento contenga todo lo que ha analizado.

Además, puede tomar esta oportunidad de reescribir de una manera más directa de las partes donde agrega algo en una lista y luego consultelo con Option7 .

  Option8  

compile su regexp

Puede compilar regexp si planea reutilizarlos muchas veces. Es más eficiente y hace posible usarlos como cualquier objeto Python.

  Option9  

"& amp;" y "& amp;"

Lo que está tratando de hacer al sustituir "& amp"; " con "& amp;":

  • merece, pero poner en una función por su cuenta

  • En realidad corresponde a un problema común ya resuelto: Decodificación de la entidad HTML .

 

The right tool

As you've said, you are not using the right tool for this task : you can't parse HTML with regexps.

A better approach would be to use an already existing parser like BeautifulSoup.

A simpler container

At the moment, you are putting data in multiple lists to zip them all at the very end. It can be a very nice technique but in our case, you put in different containers things that actually belong together. Also, you have a risk of adding too many elements in a list and having information zipped with information that should be in a different row. An easier option is to have a single list where each elements contain everything you've parsed.

Also, you can take this chance to rewrite in a more straightforward way the parts where you add something a list and then refer to it with my_list[-1].

company_data = []  for i in range(len(table)):     if bool(re.search(pattern = tick_ident_nasdaq, string = table[i])):         exchange = "NASDAQ"     elif bool(re.search(pattern = tick_ident_nyse, string = table[i])):         exchange = "NYSE"     else:         exchange = None     if exchange:         ticker = re.search(pattern = name_grab, string = table[i]).group(1)         name = re.search(pattern = name_grab, string = table[i + 1]).group(1)         name = re.sub(pattern = "&amp;", repl = "&", string = name)         cig = re.search(pattern = cigs_grab, string = table[i + 3]).group(1)         cig = re.sub(pattern = "&amp;", repl = "&", string = cig)         cig_sub = re.search(pattern = cigs_grab, string = table[i + 4]).group(1)         cig_sub = re.sub(pattern = "&amp;", repl = "&", string = cig_sub)         company_data.append((ticker, exchange, name, cig, cig_sub)) 

Compile your regexp

You can compile regexp if you plan to reuse them many times. It is more efficient and it makes it possible to use them like any Python object.

# Define regex used for parsing tick_ident_nasdaq = re.compile('href=\"http:\/\/www\.nasdaq\.com\/symbol\/') tick_ident_nyse = re.compile('href=\"https:\/\/www.nyse.com\/quote\/') name_grab = re.compile('\">(.+)<\/a></td>') cigs_grab = re.compile('^<td>(.+)</td>') amp_re = re.compile("&amp;")  company_data = []  for i in range(len(table)):     if bool(tick_ident_nasdaq.search(string = table[i])):         exchange = "NASDAQ"     elif bool(tick_ident_nyse.search(string = table[i])):         exchange = "NYSE"     else:         exchange = None     if exchange:         ticker = name_grab.search(string = table[i]).group(1)         name = name_grab.search(string = table[i + 1]).group(1)         name = amp_re.sub(repl = "&", string = name)         cig = cigs_grab.search(string = table[i + 3]).group(1)         cig = amp_re.sub(repl = "&", string = cig)         cig_sub = cigs_grab.search(string = table[i + 4]).group(1)         cig_sub = amp_re.sub(repl = "&", string = cig_sub)         company_data.append((ticker, exchange, name, cig, cig_sub)) 

"&" and "&"

What you are trying to do when substituing "&" with "&":

  • deserves to but put in a function on its own

  • actually corresponds to a common problem already solved : HTML entity decoding.

 
 
 
 
1
 
vote

Un enfoque más genérico aquí podría ser usar pandas.read_html() Función que puede analizar esta tabla en un DataFrame que sería muy conveniente para tratar con más tarde: filtrar, cortar, escribir en una base de datos (consulte to_sql() ).

Aquí hay un código de muestra para obtener el sistema de datos S & AMP; P 500:

  import pandas as pd import requests   url = "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies" response = requests.get(url)  df = pd.read_html(response.content)[0] print(df)   

y, FYI, read_html()4 está usando BeautifulSoup para HTML analizando debajo de la capucha.

 

A more generic approach here could be to use pandas.read_html() function that can parse this table into a DataFrame which would be very convenient to deal with later - filter, slice, write to a database (see to_sql()).

Here is a sample code to get the desired S&P 500 dataframe:

import pandas as pd import requests   url = "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies" response = requests.get(url)  df = pd.read_html(response.content)[0] print(df) 

And, FYI, read_html() is using BeautifulSoup for HTML parsing under-the-hood.

 
 
 
 

Relacionados problema

2  Leyendo un archivo que representa frecuencias de palabras en Wikipedia, para análisis de agrupación  ( Reading a file representing word frequencies in wikipedia for clustering analys ) 
Estoy escribiendo un sistema que ejecutará KMEANS para determinar las palabras más usadas en Wikipedia. Hago esto construyendo un conjunto de núcleo con datos...

4  Buscar artículos wikipedia con tipos específicos de enlaces de página de usuario  ( Finding wikipedia articles with specific types of user page links ) 
SELECT pl_from, NS, page_title, L_NS, L_titles, num_L, SB, IU, WP FROM ( SELECT pl_from, -- pl_from_namespace does not appear to be consistently reliable...

1  Búsqueda de Wikipedia de JavaScript usando jQuery Autocompletar  ( Javascript wikipedia search using jquery autocomplete ) 
El objetivo es consultar la API de Wikipedia con una búsqueda, y presentar al usuario las opciones de autocompletar en función de una llamada de API que muest...

3  Mostrando los cambios de un artículo de Wikipedia a medida que Git se compromete  ( Showing a wikipedia articles changes as git commits ) 
He creado un script de NodoJs de pequeño ish que toma como argumento el nombre de un artículo de Wikipedia (y, opcionalmente, una edición de Wikipedia, "ES" e...

5  Actualizar script para sitio web de MediaWiki con un complemento externo (onda 1)  ( Upgrade script for mediawiki website with one external addon wave 1 ) 
Tengo un sitio web de MediaWiki 1.33.0 con un solo complemento externo instalado (extensión externa), que es Contactage . He creado el siguiente script con ...

2  Html para infoboxes wikipedia  ( Html for wikipedia infoboxes ) 
Wikipedia usa infoboxes para muchos de sus artículos. Contienen información básica en forma estructurada sobre el tema. Tomemos, por ejemplo, los artículos so...

4  Java - Descargando artículos wikipedia  ( Java downloading wikipedia articles ) 
Este es mi primer experimento que utiliza una API de red y se conecta a Internet. Intenté escribir un programa que le brinda un artículo de Wikipedia directam...

30  Python Web-Scraps para descargar la tabla de conteos de transistor de Wikipedia  ( Python web scraper to download table of transistor counts from wikipedia ) 
He estado buscando respuestas para cómo raspar fácilmente los datos de Wikipedia a un archivo CSV con una sopa hermosa. Este es el código hasta ahora. ¿Hay un...

5  Análisis de datos de Wikipedia en Python  ( Parsing wikipedia data in python ) 
Soy nuevo en Python y me gustaría algún consejo o orientación avanzando. Estoy tratando de analizar los datos de Wikipedia en algo uniforme que pueda poner en...

3  Mapper Wiki Link: una webcrawler que arrastra los enlaces recursivamente y los imprime en un gráfico  ( Wiki link mapper a webcrawler which crawls links recursively and prints them i ) 
Me gustaría algunas sugerencias sobre cómo mejorarlo y también si alguna característica que debería agregar a este script. Estoy usando BeautifulSoup, solicit...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos