Cuando imprime la cantidad de articulos, esta mal escrito no es ‘article’, es ‘articles’ que es la lista de articulos.
print(len(articles))
Introducción
Qué aprenderás sobre la ingeniería de datos
Archivos del curso y Slides
¿Qué es la Ciencia e Ingeniería de Datos?
Roles
Configuración del ambiente
Jupyter Notebooks
Profundizando en tipos de datos
Tipos de datos
Fuentes de datos
ETL
Web scraping
Introducción a las tecnologías web
Realizar solicitudes HTTP con Python
¿Cómo trabajar con un documento HTML?
Analizando un sitio web para encontrar las directivas a utilizar al hacer un web scrapping
Solicitudes a la web: Requests
Implementando nuestro web scrapper: Configuración
Implementando nuestro web scrapper: Obteniendo enlaces del front page
Implementando nuestro web scrapper: Obteniendo artículos
Obtención de datos del Artículo
Persistiendo la información "scrapeada"
Pandas
Introducción a Pandas
Estructura de datos: Series
Estructura de datos: DataFrames
Índices y selección
Data wrangling con Pandas
Creación de la receta: preparando la automatización
¿Cómo trabajar con datos faltantes?
Operaciones con Series y DataFrames
Limpiando detalles adicionales
Limpiando detalles en nuestro proyecto
Enriquecimiento de los datos
Valores duplicados en Jupyter
Valores duplicados en Python
Visualización de datos
Intro a Sistemas de Datos
Introducción a los sistemas de datos
Automatización del Pipeline
Cargando datos a SQLite
Contenido Bonus
¿Por qué usar la nube?
Aún no tienes acceso a esta clase
Crea una cuenta y continúa viendo este curso
Aportes 81
Preguntas 13
Cuando imprime la cantidad de articulos, esta mal escrito no es ‘article’, es ‘articles’ que es la lista de articulos.
print(len(articles))
Si a alguien le sale el error:
TypeError: object of type ‘NoneType’ has no len()
en la linea de codigo:
return result[0].text if len(result) else ''
Se soluciona cambiando la linea de código por:
return result[0].text if result != None else ''
El mejor profe del mundo
un error que tuve probando es que algunos url obtetinos eran tipo: ** https://www.viveusa.mx** por lo cual caía en la categoría de un root_path , razon por la cual daba error porque terminaba creando links que eran como https://www.eluniversal.com.mx//https://www.viveusa.mx entonces para solucionar esto cree un nuevo chequeo
is_other_host = re.compile(r'^https?://.+/$')
y para ver que tipo de link es quedo asi:
if is_well_formed_link.match(link):
returnlink
elif is_other_host.match(link):
returnlink
elif is_root_path.match(link):
return'{}{}'.format(host, link)
else:
return'{host}/{uri}'.format(host=host, uri=link)
Para el Tiempo (82 articulos) ( Enlace articulo: ‘.title-container a’ Titulo: ‘.titulo-principal-bk h1’ y el Cuerpo: ‘.contenido’ )
Para Semana (75 articulos) ( Enlace articulo: ‘.article-h a’ Titulo: ‘.tittleArticuloOpinion’ y el Cuerpo: ‘#contentItem’ )
Me aparecieron tres errores más que agregue a las excepciones:
from urllib3.exceptions import NewConnectionError
from requests.exceptions import ConnectionError
from socket import gaierror
Para saber más de expresiones regulares con Python, Platzi tiene un articulo escrito sobre eso: https://platzi.com/blog/expresiones-regulares-python/
Igual acá está la documentación en el sitio de Python: https://docs.python.org/3/library/re.html
A quienes les aparezca este error:
return result[0].text if len(result) else ''
TypeError: object of type 'NoneType' has no len()
Lo pueden solucionar cambiando len(result) por result!=None
The special characters are:
"." Matches any character except a newline.
"^" Matches the start of the string.
"$" Matches the end of the string or just before the newline at
the end of the string.
"*" Matches 0 or more (greedy) repetitions of the preceding RE.
Greedy means that it will match as many repetitions as possible.
"+" Matches 1 or more (greedy) repetitions of the preceding RE.
"?" Matches 0 or 1 (greedy) of the preceding RE.
*?,+?,?? Non-greedy versions of the previous three special characters.
{m,n} Matches from m to n repetitions of the preceding RE.
{m,n}? Non-greedy version of the above.
"\\" Either escapes special characters or signals a special sequence.
[] Indicates a set of characters.
A "^" as the first character indicates a complementing set.
"|" A|B, creates an RE that will match either A or B.
(...) Matches the RE inside the parentheses.
The contents can be retrieved or matched later in the string.
(?aiLmsux) Set the A, I, L, M, S, U, or X flag for the RE (see below).
(?:...) Non-grouping version of regular parentheses.
(?P<name>...) The substring matched by the group is accessible by name.
(?P=name) Matches the text matched earlier by the group named name.
(?#...) A comment; ignored.
(?=...) Matches if ... matches next, but doesn't consume the string.
(?!...) Matches if ... doesn't match next.
(?<=...) Matches if preceded by ... (must be fixed length).
(?<!...) Matches if not preceded by ... (must be fixed length).
(?(id/name)yes|no) Matches yes pattern if the group with id/name matched,
the (optional) no pattern otherwise.
Una lástima como está dictado este curso. Estoy haciendo la ruta de Data Science y está completamente desconectado de lo visto hasta ahora. Hice todos los cursos de Python hasta ahora en la ruta, además de que ya tenía experiencia con el lenguaje, y se hace muy muy díficil de seguir. MAL
Si el body se divide en distintos párrafos como scrappeo? solo me toma el primero
esta clase estuvo intensa
Ya logré rasgar la página del Universal. Y que pena decirlo pero ni la página del Universal, ni del Pais, ni de Semana ni del Tiempo he podido rasgarlas con el código que dan acá… es más ni los títulos pude obtenerlos. Los aportes de los compañeros la verdad ni para que se molestan en postiar cosas que no sirven. Y es de entender porque:
A) Un webscraper profesional de Periódicos en linea vale unos 3,000 USD
B) Aoresti no va a poner aquí gratis un scraper profesional porque estaría regalando su trabajo como desarrollador.
C) Platzi no lo va a exigir tampoco.
D) Si uno quiere que funcione el .YAML debe utilizar otra libreria porque Beautiful Soup 4 se revienta cuando las clases (class) tienen espacios. La clase que contiene el texto de los articulos del universal tiene espacios.
E) Logré arreglar el código con BS4 pero sin YAML y desarrollé una heurística bastante extensa y compleja para extraer el solo texto sin los marcadores HTML por que hasta los mismos articulos tienen anuncios, incrustados, publicidad, scripts, etc… Y eso toca borrarlo de la búsqueda para obtener el texto limpio.
Para todo esto me gasté unas 5 horas o más, y obvio no voy a regalar mi código!
Tengo el siguiente error:
result = self._select(self._queries('article_body'))
TypeError: 'dict' object is not callable
me parece extraño porque estoy haciendo el mismo código que el profesor, pero aun asi no funciona.
Alguien sabe por qué?
para el que le salga error al mostrar print(len(article)) es articles asi:
print(len(articles))
Una de las cosas se me han hecho mas duras es el tema de encontrar las clases en los html, y que toca estar revisando el cogido con compañeros pero he aprendido un montón. (cada clase es casi una hora, los 10 a 15 minutos mas un montón de tiempo buscando por que no me funciona)
Miren, la verdad si está algo complicado el curso. Hay que tener en cuenta que las estructuras de las paginas cambian, lo cual es bueno ya que nos hace buscar y deducir como vamos a realizar la busqueda ahora, y no solo copiar y pegar lo que escribio David. Sin embargo, está mas que claroque este curso no es para principiantes en python ni en la programación. Recomiendo tomar la ruta de fundamentos de programación…después de eso los 3 o 4 cursos que hay actualmente de python, incluendo el de POO y algoritmos, entonces sí regresar aquí 😄
está un poco complicado pero es porque manejo python básico. La cosa estará en práctica porque ahora puedo repetir lo que hizo el profesor pero hacer ese análisis en otra cosa me va a costar un millón.
Me funcionó perfecto!
Qué buen curso!!!
Quizás con esto se entienda un poco mejor lo que hicimos con re.compile()
|
|
Link al articulo: https://pynative.com/python-regex-compile/
Hay un absurdo error en la clase NewsPage que hace que “parezca que recuperan articulos” pero en realidad es el mismo texto de la página principal. Me tomó mas de una hora depurar ese error por que no se ve a simple vista. Para todos los que tienen articulos recuperados, revisen el contenido de los mismos!!!
Cuando se usan este tipo de tags para identificar el body de un articulo solo trae el primer parrafo porque, segun tengo entendido, select selecciona el primer bloque de html que cumple las condiciones, como deberiamos hacer para traer todo el body? gracias!
Así sale mi éxito:
INFO:__main__:Start fetching article at /opinion/gerardo-velazquez-de-leon/el-zoom-el-mejor-defensor-de-los-entrenadores
INFO:__main__:YAAASSSS!
Las expresiones regulares vistas en clase:
r'^https?://.+/.+$'?
r --> indica a python que es un string
^ --> inicio del patron
? --> caracter opcional
.+ --> una o más letras
$ —> final del patrón
He logrado hacer el ejercicio de insertarle los contenidos de las páginas de “El Pais” y de una página de sátira llamada “El Deforma”. SI les es útil, les comparto mi repositorio del curso
Esta clase tubo mucho nivel, y eso es bueno
Wow se ve genial cuando empieza a jalar los titulos y las url
🤯
El problema es que cuando no corre o no funciona la rutina cargada y el sistema de comentarios no ha tenido la solución previamente, sencillamente te estancas hasta quien sabe cuando responda el equipo de Platzi. Les recomiendo (a Platzi) que en sus videos muestren la sintaxis y funcionalidad de las expresiones. Video es solo el profesor escribiendo y escribiendo, hablando sin ejemplificar didacticamente. Solo se nota que transcribe un script previo y así cualquiera podría reproducir un video “enseñando”
Admito que en los videos que ya venían durando aproximadamente 10 minutos me tardaba 30 o 40 minutos en seguirle el paso. Ya veo que es solo el comienzo.
Hola, yo tengo una dudilla. Creo que lo entiendo todo razonablemente bien, pero he ido construyendo el scraper orientado a sacar la data de la PlayStore y no de los diarios y me encuentro con un problema:
Al ir a sacar la info del body, me encuentro con diferentes elementos html que corresponden al div donde se encuentra la descripción, pero al ir al utilizarlos en el config y correr el script me dice que no hay body.
Al revisar el código fuente de la PlayStore, vemos que el div más “pegado” a la descripción no tiene un class sino un jsname. Quizá el problema venga de por ahí, pero no tengo claro exactamente por qué. He probado poniendo ese jsname en el config, también otros class que hay en divs más “arriba” en el árbol del código. En ninguno de los casos lo he logrado.
A ver si alguien tiene alguna idea al respecto 😃
PD: Con los diarios y los parámetros mencionados en las clases sí funciona bien.
Les recomiendo que hagan un try catch en la funcion de visit, ya que el request puede tener datos comprimidos y el parse con beautifulsoup nos marcará error:
try:
response = requests.get(url)
response.raise_for_status()
self._html = BeautifulSoup(response.text, 'html.parser')
except:
self._html = BeautifulSoup('')
el codigo del profesor tiene un bug:
en el archivo main.py…en la funcion ‘_build_link’ todos los links se estan llendo al ‘else’ y no funcionan:
def _build_link(host, link):
if is_well_formed_url.match(link):
return link
elif is_root_path.match(link):
print('{host}{uri}'.format(host=host, uri=link))
return '{host}{uri}'.format(host=host, uri=link)
else:
print('{host}/{uri}'.format(host=host, uri=link))
return '{host}/{uri}'.format(host=host, uri=link)```
coloque un print en cada if statement para comprobar que estaba sucediendo con el codigo, en la foto se puede ver que: agrega la homepage + / + el link, por eso en el path quedan con doble //, y en el que es link queda repeetido https:xxxxhtpps:dfdfffd y por eso sale la excepcion.
 11.04.49 p. m..png](https://static.platzi.com/media/user_upload/Captura%20de%20Pantalla%202020-05-29%20a%20la%28s%29%2011.04.49%20p.%C2%A0m.-67b3308b-a709-44e0-ba94-71b694a7b57e.jpg)
el problema esta en las expresiones regulares que utilizamos para identificar si era una url o un path, aca esta el cambio generado para poder que funcionen correctamente:
is_well_formed_url = re.compile(r"^(https?😕/)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?$") #expresiones regulares y hace match eje: https://example.com/hello
is_root_path = re.compile(r"(/?[a-z0-9-.~%!$&’()*+,;[email protected]]+(/[a-z0-9-.~%!$&’()+,;=:@]+)/?|/)")```
y este es el resultado, ya funcionan bien los statements y puedes comprobar que cuando hay path no repite // como lo hacia antes:
INFO:main:Start fetching article at http://www.unionyucatan.mx/articulo/2020/05/05/espectaculos/survivor-mexico-conductor-y-todo-lo-que-debes-saber
INFO:main:Article fetched!
Survivor México, conductor y todo lo que debes saber
INFO:main:Start fetching article at https://www.clubeluniversal.mx/content/suscripciones
INFO:main:Article fetched!
INFO:main:Start fetching article at https://www.eluniversalvideo.com.mx/videos/v_NeA7EiUQghc.html
WARNING:main:Invalid article. there is no body.
INFO:main:Start fetching article at https://interactivo.eluniversal.com.mx/2020/ciencia-matematicas-covid-19/
WARNING:main:Invalid article. there is no body.
INFO:main:Start fetching article at /universal-deportes/mas-deportes/amlo-acusaciones-de-corrupcion-ana-guevara-son-politicas
http://www.eluniversal.com.mx/universal-deportes/mas-deportes/amlo-acusaciones-de-corrupcion-ana-guevara-son-politicas
INFO:main:Article fetched!
Acusaciones de corrupción a Ana Guevara son políticas: AMLO
INFO:main:Start fetching article at https://www.eluniversalvideo.com.mx/videos/v_er2il4TIgR4.html
WARNING:main:Invalid article. there is no body.
INFO:main:Start fetching article at https://www.eluniversal.com.mx/o
para las personas que quieran profundizar mas en el tema de expresiones regulares, les dejo esta pagina:
Clase muy llena de información, pero muy clara. Gracias.
Les paso mi config con dos ejemplos que me funcionaron:
news_sites:
lanacion:
url: https://www.lanacion.com.ar
queries:
homepage_article_links: ".com-title a"
article_body: "p.com-paragraph"
article_title: "h1.com-title"
elpais:
url: https://elpais.com
queries:
homepage_article_links: "h2.c_t a"
article_body: ".a_c p"
article_title: "h1.a_t"
Dos errores que me ocurrieron:
Había un link de El Pais que tenía un espacio al comienzo, algo así:
' https://www.eluniversal.com.co/multimedia'
Esto provocaba que el código se cayera al no encontrar la página correcta. Se solucionó con un .strip()
así
return set(link['href'].strip() for link in link_list)
El error anteriormente mencionado debió haberlo captura el try except
, pero aún así se caia el código. Lo solucioné importando el HTTPError
desde requests
en lugar de urllib.error
from requests import HTTPError
Y bueno, un último error fué TypeError: object of type ‘NoneType’ has no len()
, pero esto ya lo mencionaron en otro comentario. Yo lo solucioné así:
return None if result is None else result[0].text
Obtengo el siguiente error:
File "C:\Users\Joel\Documents\web_scrapper_curso_data_eng\news_page_objects.py", line 48, in body
result = self._select(self._queries['article_body'])
KeyError: 'article_body'```
ya intente cambiando el article_body por algun otro identificador, pero sigo sin poder resolverlo. Será que no estoy tomando el identificador correcto?
Me salía el error TypeError: _log() got an unexpected keyword argument ‘exc_inf’ al intentar obtener los artículos, solamente cambien en la funcion _fetch_article la linea logger.warning(‘Error while fechting the article’) eliminando el parámetro exc_inf=False
Este error me salió después de varios días probando es scrapper, supongo que fue un articulo que tenia un HTML diferente a los demás
Me gustaría conocer más a fondo cómo encontrar los queries de las páginas de internet, entiendo que todo el código se basa en estos y a medida que pasa el tiempo se van actualizando lo que genera errores en el web_scrapper
Así como David comenta, aquí se mezclan viejas practicas con nuevas practicas y el uso de conceptos mas avanzados de Python como los decoradores, No traten de entender todo a la primera, sigan con el curso y después vuelvan por el segundo intento o después de revisar mas recursos y practicar
Que clase tan increíble, recoge de muy buena manera los conceptos de las anteriores y conecta con el curso de Python, vamos por mas en esta carrera por el ML.
Si quieren agregarle colores a sus logs de python les comparto este enlace
Super cool!
web_scrapper\common.py", line 10, in config
with open(‘config.yaml’, mode=‘r’) as f:
FileNotFoundError: [Errno 2] No such file or directory: ‘config.yaml’
Unused variable ‘e’
Me siento como un hacker con este curso
buen dia, alguien que me pueda ayudar con el siguiente error
Traceback (most recent call last):
File "main.py", line 75, in <module>
_news_scraper(args.news_site)
File "main.py", line 29, in _news_scraper
article = _fetch_article(news_site_uid, host, link)
File "main.py", line 49, in _fetch_article
if article and not article.body:
File "/home/gerardino/web_scrapper_curso_data_eng/news_page_objects.py", line 51, in body
return result[0].text if len(result) else ''
TypeError: object of type 'NoneType' has no len()```
mi codigo esta en aqui
https://drive.google.com/open?id=1M41wTo60NGEGQgVZzdaLTVMv_I76uksa```
Muy interesante , gracias por ensenarnos esos trucos para mejorar el codigo!
Estimados.
Tengo un problema al ejecutar el archivo main.py.
Por favor si alguien me puede ayudar.
INFO:root:Beginning scraper for http://www.eluniversal.com.mx
Traceback (most recent call last):
File “main.py”, line 89, in <module>
_news_scraper(args.news_site)
File “main.py”, line 24, in _news_scraper
homepage = news.HomePage(news_site_uid, host)
File “C:\Users\mmora\OneDrive\Carpeta Sincronizada\Platzi\Ingeniero de datos\platziData-5e1f90191f3a83497c2c7078a9acfeac61f24a24\web_scrapper_curso_data_eng\news_page_objects.py”, line 30, in init
super().init(news_site_uid, url)
TypeError: super() takes at least 1 argument (0 given)
Gracias
Hola, antes de terminar de correr todo me apareció lo siguiente, creo que no es un error como tal ¿Alguno me podría indicar qué es?
Excelente clase
Me pasa que el scraper funciona, pero hay algunas noticias que están en un formato diferente (en video) y la etiqueta para traerlas es diferente a las que son en texto. ¿cómo puedo agregar esa funcionalidad, que si son en texto busque una etiqueta para traer el título y si es en vídeo, busque otra diferente?
interesante!
Si no entendiste nada sobre las expresiones regulares aqui en platzi esta este excelente curso
El paso a paso con el profesor, me resulto muy bien. He aquí el resultado:
Uff cada ves se ve que hay que repetir mucho para ir entendiendo…
las expresiones regulares las comprendo no son tan complejas pero me perdi un poco en la jerarquia del desarrollo de los objetos
import argparse
import logging
logging.basicConfig(level=logging.INFO)
import re
from requests.exceptions import HTTPError
from urllib3.exceptions import MaxRetryError
import news_page_objects as news
from common import config
is_well_formed_url= re.compile(r'^https?://.+/.+$') # i.e. https://www.somesite.com/something
is_root_path = re.compile(r'^/.+$') # i.e. /some-text
logger = logging.getLogger(__name__)
def _news_scraper(news_site_uid):
host = config()['news_sites'][news_site_uid]['url']
logging.info('Beginning scraper for {}'.format(host))
logging.info('Finding links in homepage...')
homepage = news.HomePage(news_site_uid, host)
articles = []
for link in homepage.article_links:
article = _fetch_article(news_site_uid, host, link)
if article:
logger.info('Article fetched!')
articles.append(article)
print(article.title)
print(len(articles))
def _fetch_article(news_site_uid, host, link):
logger.info('Start fetching article at {}'.format(link))
article = None
try:
article = news.ArticlePage(news_site_uid, _build_link(host, link))
except (HTTPError, MaxRetryError) as e:
logger.warn('Error while fetching article!', exc_info=False)
if article and not article.body:
logger.warn('Invalid article. There is no body.')
return None
return article
def _build_link(host, link):
if is_well_formed_url.match(link):
return link
elif is_root_path.match(link):
return '{host}{uri}'.format(host=host, uri=link)
else:
return '{host}/{uri}'.format(host=host, uri=link)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
news_site_choices = list(config()['news_sites'].keys())
parser.add_argument('news_site',
help='The news site that you want to scrape',
type=str,
choices=news_site_choices)
args = parser.parse_args()
_news_scraper(args.news_site)```
import yaml
__config = None
def config():
global __config
if not __config:
with open('config.yaml',mode = 'r') as f:
__config =yaml.safe_load(f)
return __config```
cual es el curso de Python que tanto habla David Aroesti ? me lo pueden compartir por favor
Logrado, aunque tuve que detenerme a leer muchas veces el código.
el reto es hacer un scrapper propio para otro tipo de información que no sea periódicos.
news_sites:
eluniversal:
url: http://www.eluniversal.com.mx
queries:
homepage_article_links: '.field-content a'
article_body: '.field-name-body'
article_title: '.pane-content h1'
elpais:
url: https://elpais.com
queries:
homepage_article_links: '.articulo-titulo a'
article_body: '.articulo-cuerpo'
article_title: '.articulo-titulo'```
me aparece el siguiente error cuando ejecuto “python main.py eluniversal”
print(len(article))
TypeError: object of type ‘ArticlePage’ has no len()
Paso 4: Obtención de datos del Artículo
scraping.py
1- se modifica _news_scraper, se inicializa la función _fetch_article en la variable article.
2- en la funcion _fetch_article se inicializa article en None. luego se realiza programacion defensiva, si todo va bien, se guarda en article.
3- se genera expresiones regulares, ‘import re’ con el fin de encontrar la estructura de los links.
4- se crea la funcion _build_link para armar los links y se ocupa el modulo re.
import argparse
import logging
import news_page_objects as news
import re #se importa expresiones regulares
from requests.exceptions import HTTPError #se importa el error
from config_yaml import config
logging.basicConfig(level=logging.INFO) #se inicia en nivel basico para que informe durante el proceso
logger = logging.getLogger(__name__) #se obtiene la referencia del logging con la variable globar que es __name__
def _news_scraper(news_site_uid):
host = config()['news_sites'][news_site_uid]['url'] #se llama al url especifico desde el argumento escojido, x ejemplo 'eluniversal' o 'elpais'
logging.info('Comenzanco el scraping en: {}'.format(host))
homepage = news.HomePage(news_site_uid, host) #se inicializa la clase HomePage, el host es el link que se encuentra en el url de config.yaml
articles = [] #lista de articulos que se encontrarán
for link in homepage.article_links:
article = _fetch_article(news_site_uid, host, link) #se crea esto para ordenar en la funcion _fetch_article
if article: #se ejecuta si es que hay un articulo
logger.info('se encontro el articulo')
articles.append(article) #se agregan los articulos a la lista de articulos
print('titulo = {}'.format(article.title)) #printea el titulo del articulo,
print('cantidad de articulos es de : {}'.format(len(article))) #se printea cantidad de articulos
def _fetch_article(news_site_uid, host, link): #funcion que ordena que elemento entregar y que no,
logger.info('esta buscando el archivo en {}'.format(link)) #este logger explica lo en que link está buscando
article = None
try:
article = news.ArticlePage(news_site_uid, _build_link(host, link))
except (HTTPError) as e: #programación defensiva, en caso de que este error ocurra.
logger.warning('Error mientras se buscaba el articulo', exc_info= False) # exc_info= False no muestra el error para no llenar la consola de basura
if article and not article.body: #quiere decir si hay articulo, pero no tiene article.body se ejecuta
logger.warning('articulo invalido, no hay cuerpo en el articulo')
return None #retorna nada porque no nos sirve
return article
is_well_formed_link = re.compile(r'^https?://.+/.+$') #esta es una expresión regular, ejemplo de la expresion regular https://example.com/hello
is_root_path = re.compile(r'^/.+$') #ejemplo, /some-text
# # ^ = quiere decir que es el inicio del patron, ? = la letra que está al lado izquierdo se encuentra o no,
#.+= expresa 1 o más letras, $ = finaliza
def _build_link(host, link):
if is_well_formed_link.match(link): #retorna el link, el martch es si lo encuentra
return link
elif is_root_path.match(link): #construye el link, en caso que este mal formado
return '{}/{}'.format(host, link)
else:
return '{}/{}'.format(host, link)
if __name__ == '__main__':
parser = argparse.ArgumentParser('siempre debe iniciar el parse así') #escribir dentro del parentesis es opcional
news_site_choices = list(config()['news_sites'].keys()) #se inicializa hacia la def config() que está dentro de config_yaml
parser.add_argument('news_site' # 'news_site' es el nombre del argumento y de los comandos
,help= 'Escoge el sitio el cual quieres buscar' # este es el mensaje que saldrá
,type= str # este es el tipo
,choices= news_site_choices)
arg = parser.parse_args() #esta linea es para pedir un objeto con el parse para luego poder llamarlo en _news_scraper(arg.news_site)
_news_scraper(arg.news_site)
A mi la verdad no me funciona nada. Tal vez cambiaron los formatos de los enlaces y no puedo reconfigurar el YAML.
para lo que tienen windoes pueden bajar la consola cmder, el profe en una clase lo sugirio.
les dejo el link
https://cmder.net/
Como la mayoria, perdido, me imagino que somos los de MinTic… si me pongo a leer comentarios me tranquilizo, porque la verdad apenas arranque con el tema de la programacion, me parece fascinante todo lo que podemos lograr, y se que que hay muchisimo camino por recorrer para aprender las bases y asi poder entender con claridad lo que se esta programamdo.
Funcionó muy bien, sin embargo al llegar a uno de los artículos el programa se bloqueo al parecer por un tipo de error diferente al que se intentó atrapar en el algoritmo:
¡Está VIVOOOOO!!! Funciona mi webscraper 😃
Por si les paso; en mi scraper encontre algunos articulos en pdf, por ahora los estoy omitiendo, con la expresion
is_pdf = re.compile(r'.+pdf$')
#Y sobre la funcion _build_link agrege otra validacion
def _build_link(host,link):
if is_pdf.match(link):
return False
elif is_well_formed_link.match(link):
return link
elif is_root_path.match(link):
return '{}{}'.format(host,link)
else:
return '{}/{}'.format(host,link)
#y en la funcion de fetch_article una validacion del retorno _build_link
def _fetch_article(news_site_uid,host,link):
logger.info("Start fetching article at {}".format(link))
article = None
try:
if _build_link(host,link):
article = news.ArticlePage(news_site_uid,_build_link(host,link))
else:
article = False
A quiénes les ha resultado muy complicado llegar hasta aquí o no les corre el código, tomen los cursos introductorios de Python, pero sobre todo Programación Orientada a Objetos, lo que es herencia y encapsulamiento.
Disfruten cada cosa nueva que aprendan, no se frustren.
Sean pacientes con su propio ritmo y amables con ustedes mismos. Agradecerse y felicitarse por cada cosa nueva que aprendan.
Se ve complicado, pero es entender el ¿por qué? lo que los va ayudar a ser mejores programadores.
¿por qué usa tantos archivos distintos si con jupyter era más fácil? ¿por qué usa self? ¿por qué las variables tiene un _variable? ¿qué son esas librerías? etc…
La respuesta a la mayoría de esas preguntas está en POO y leyendo la documentación.
Intenten entender cada línea de código. No copien y peguen solamente, entiendan cuál es el propósito.
Se logro el objetivo con ambos periodicos apesar de errores que tenia, hay que reconocer que el profesor tiene razon cuando dice ‘‘estamos para ayudarte’’, estamos los estudiantes porque no he visto el primer comentario que responda y hay muchas preguntas por resolver.
Esto está muy denso.
No se ha entendido mucho pero se logró completar el ejercicio.
Hola amigos me ayudan con los tags de el pais, cambiaron
Obtuve en estos pero no funcionan del todo.
elpais:
url: http://elpais.com
queries:
homepage_article_links: '.headline a'
article_body: '.description a'
article_title: '.headline b'```
Para el caso de El País agregué un par de errores con noticias de otros sitios.
from urllib3.exceptions import DecodeError
from requests.exceptions import ContentDecodingError
except(HTTPError, MaxRetryError, DecodeError, ContentDecodingError) as e:
logger.warning('Error while fetching the article', exc_info=False)
return None
La configuración del archivo config.yaml con los datos a la fecha:
news_sites:
eluniversal:
url: https://www.eluniversal.com.mx
queries:
homepage_articles_links: '.titulo a'
article_body: '.field-name-body'
article_title: 'h1'
elpais:
url: https://elpais.com
queries:
homepage_articles_links: 'h2 > a'
article_body: 'h1'
article_title: '.a_b article_body > p'
Si a alguien le aparece el error: TypeError: object.init() takes exactly one argument (the instance to initialize). Debe eliminar la linea: super().init(news_site_uid, url)
Porque parece ya no hace falta en python para volver a llamar a la función
Haciendo la práctica me encontré con un problema puesto que en uno de mis host, para acceder a la información se le añadía un path y cuando quería acceder a la noticia, como la noticia tenia path relativos, se duplicaba el path del host con el path relativo. Para arreglar ese problema realice el siguiente método.
def _convert_url_host(host):
host_parser = urlparse(host)
if host_parser.path=='':
return host
else:
return '{scheme}://{domain}'.format(scheme=host_parser.scheme,domain=host_parser.netloc)
Espero les sirva 😁
def _convert_url_host(host):
host_parser = urlparse(host)
if host_parser.path=='':
return host
else:
return '{scheme}://{domain}'.format(scheme=host_parser.scheme,domain=host_parser.netloc)
La cantidad de tiempo que te ahorras en revisiones usando por ejemplo VSCode 😃
Sería bueno utilizar la programación asíncrona o multihilo para mejorar el rendimiento del scraper.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.