LISTA DE USER AGENTS

 WINDOWS + GOOGLE CHROME


Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36


MAC SAFARI 11.1

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15


WINDOWS INTERNET EXPLORER

Mozilla/5.0 CK={} (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko


LINUX CHROME 44

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36


ANDROID CHROME 70

Mozilla/5.0 (Linux; Android 7.1.2; AFTMM Build/NS6265; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.110 Mobile Safari/537.36


01100110 01101001 01101110 00100000 01100100 01100101 00100000 01100011 01101111 01100100 01101001 01100111 01101111

RETURN

TypeError: 'Rule' object is not iterable

Este error ocurre porque falta una coma en el parametro rule de de la clase que hereda CrawlSpider

así se puede encontrar

rules = ( 

Rule(
LinkExtractor(
allow = r'/Hotel_Review'
), follow=True
, callback= "parce_hotel"
)
)


así se debe ver

rules = ( 

Rule(
LinkExtractor(
allow = r'/Hotel_Review'
), follow=True
, callback= "parce_hotel"
),
)

sino no lo toma como un objeto iterable

pequeños detalles, grandes errores


01100110 01101001 01101110 00100000 01100100 01100101 00100000 01100011 01101111 01100100 01101001 01100111 01101111

RETURN


QT Designer - aplicacion comentada PyQt5

Link al repositorio acá 

import sys
from PyQt5 import uic, QtGui
from PyQt5.QtWidgets import QMainWindow, QApplication


class MainWindow(QMainWindow): #nota7: cuando llama a la clase, viene por aca

def __init__(self): #nota8: el __init__ de initialized, es el codigo que SIEMPRE se ejecuta, el def ventanaNueva no se ejecuta porque esta fuera de aca, aca se conectan botones, los eventos que vayan a pasar, las restricciones, etc...
super().__init__() #superposiciona el init, siempre va.
uic.loadUi('gui_1.ui', self) #aca se carga la gui
self.pushButton.clicked.connect(self.ventanaNueva) #aca conecta el boton de nombre pushButton que nos da el designer y lo conectamos a la funcion ventanaNueva

def ventanaNueva(self):
gui2.show() #y aca muestra la ventana y nada mas
#gui2.showMaximized() #esto esta para que prueven cambiando y viendo como cambia
#gui2.showMinimized() #esto esta para que prueven cambiando y viendo como cambia

class Window2(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi('gui_2.ui', self)

if __name__ == '__main__': #nota1: esto siempre va, es para que el programa siempre ejecute esta parte
app = QApplication(sys.argv) #Nota2: aca crea un objeto para hacer las aplicaciones
gui = MainWindow() #Nota3: todas las ventanas tendran su armado mediante esto, un objeto del tipo variable=Clase_del_objeto()
gui2= Window2() #Nota4: para la gui2
gui.show() #Nota5: aca muestra la gui principal la main, como ya la tiene armada(en Nota3) ahora la muestra mediante el metodo .show(), hay varias maneras, showMaximiced() la muestra maximixada por ej
sys.exit(app.exec_()) #Nota6: esto es para que quede abierto, sino se cierra el programa, queda ejecutandose



Haciendo el ejecutable

asta acá puedes hacer tu programa y ejecutarlo a medida que vas modificando y agregando interfaces pero a la hora de hacer el ejecutable es necesario hacer cambios...

al momento de usar auto-py-to-exe, muy práctico a la hora de exportar me encontré con algunos problemas, pero recurrí a usar pyuic5 para transformar los .ui a .py y así usar todos los .py en el programa de auto-py-to-exe (donde encontrarlo

hay que instalar las librerías necesarias

$ pip install pyqt5-sip
$ pip install pyqt5

con la terminal abierta en la ubicación donde estan los .ui se ingresa el siguiente codigo, usando pycharm puedes usar ALT+F12 y se abre abajo.

pyuic5 -x gui_1.ui -o gui_1_ui.py

la forma es: pyuic5 -x <archivo .ui> -o <nuevo_archivo .py>
el nombre de archivo.ui pasa a archivo_ui.py

para nuestro programa usamos...

>pyuic5 -x gui_1.ui -o gui_1_ui.py

>pyuic5 -x gui_2.ui -o gui_2_ui.py

Esto amerita unos cambios en el codigo...

import sys
from PyQt5 import uic, QtGui
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5 import QtWidgets

#####
from gui_1_ui import * # NUEVO
from gui_2_ui import * # NUEVO


#####

# class MainWindow(QMainWindow): #nota7: cuando llama a la clase, viene por aca
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): # NUEVO

def __init__(
self): # nota8: el __init__ de initialized, es el codigo que SIEMPRE se ejecuta, el def ventanaNueva no se ejecuta porque esta fuera de aca, aca se conectan botones, los eventos que vayan a pasar, las restricciones, etc...
# super().__init__() # superposiciona el init, siempre va.
# uic.loadUi('gui_1.ui', self) # aca se carga la gui
QtWidgets.QMainWindow.__init__(self) # NUEVO
self.setupUi(self) # NUEVO
self.pushButton.clicked.connect(
self.ventanaNueva) # aca conecta el boton de nombre pushButton que nos da el designer y lo conectamos a la funcion ventanaNueva

def ventanaNueva(self):
gui2.show() # y aca muestra la ventana y nada mas
# gui2.showMaximized() #esto esta para que prueven cambiando y viendo como cambia
# gui2.showMinimized() #esto esta para que prueven cambiando y viendo como cambia


# class Window2(QMainWindow):
class Window2(QtWidgets.QWidget, Ui_Form): # NUEVO
def __init__(self):
QtWidgets.QMainWindow.__init__(self) # NUEVO
self.setupUi(self) # NUEVO
# super().__init__()
# uic.loadUi('gui_2.ui', self)


# if __name__ == '__main__': # nota1: esto siempre va, es para que el programa siempre ejecute esta parte
# app = QApplication(sys.argv) # Nota2: aca crea un objeto para hacer las aplicaciones
# gui = MainWindow() # Nota3: todas las ventanas tendran su armado mediante esto, un objeto del tipo variable=Clase_del_objeto()
# gui2 = Window2() # Nota4: para la gui2
# gui.show() # Nota5: aca muestra la gui principal la main, como ya la tiene armada(en Nota3) ahora la muestra mediante el metodo .show(), hay varias maneras, showMaximiced() la muestra maximixada por ej
# sys.exit(app.exec_()) # Nota6: esto es para que quede abierto, sino se cierra el programa, queda ejecutandose

app = QApplication([]) # NUEVO
gui = MainWindow() # NUEVO
gui2 = Window2() # NUEVO
gui.show() # NUEVO
app.exec_() # NUEVO

luego en una terminal de anaconda, ejecutamos Auto-py-to-exe


en Additional Files, agregamos los .py nuevos



pyinstaller --noconfirm --onefile --console --name "ejemplo4" --add-data "C:/Users/Gaston/PycharmProjects/ejemplo/gui_1_ui.py;." --add-data "C:/Users/Gaston/PycharmProjects/ejemplo/gui_2_ui.py;."  "C:/Users/Gaston/PycharmProjects/ejemplo/main.py"

el programa funciona pero se habre una terminal, con cambiarlo en  Console Window es suficiente


pyinstaller --noconfirm --onefile --windowed --name "ejemplo5" --add-data "C:/Users/Gaston/PycharmProjects/ejemplo/gui_1_ui.py;." --add-data "C:/Users/Gaston/PycharmProjects/ejemplo/gui_2_ui.py;."  "C:/Users/Gaston/PycharmProjects/ejemplo/main.py"


el codigo limpio queda asi...

import sys
from PyQt5 import uic, QtGui
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5 import QtWidgets
from gui_1_ui import *
from gui_2_ui import *


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

def __init__(
self):
QtWidgets.QMainWindow.__init__(self)
self.setupUi(self)
self.pushButton.clicked.connect(
self.ventanaNueva)

def ventanaNueva(self):
gui2.show()


class Window2(QtWidgets.QWidget, Ui_Form):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.setupUi(self)


app = QApplication([])
gui = MainWindow()
gui2 = Window2()
gui.show()
app.exec_()

01100110 01101001 01101110 00100000 01100100 01100101 00100000 01100011 01101111 01100100 01101001 01100111 01101111

RETURN


Manejo de errores en Web Scraping

Anticipar el faltante de contenido string en una extracción: 

for noticia in noticias:
item = ItemLoader(Noticia(), response.body)
titular = noticia.find('a').text
descripcion = noticia.find('p').text
item.add_value('titular', titular)
item.add_value('descripcion', descripcion)
yield item.load_item()

cuando se extraen datos, esperando siempre que haya texto en su contenido puede ocurrir el error de

 AttributeError: 'NoneType' object has no attribute 'text'

significa que espera extraer algo pero es de tipo NONE ahí esta el conflicto, se resuelve introduciendo un if que anticipe esta situación.

for noticia in noticias:
item = ItemLoader(Noticia(), response.body)

titular = noticia.find('a')
descripcion = noticia.find('p').text

if (titular != None):
titular = titular.text
else:
titular = 'N/A'

item.add_value('titular', titular)
item.add_value('descripcion', descripcion)
yield item.load_item()

01100110 01101001 01101110 00100000 01100100 01100101 00100000 01100011 01101111 01100100 01101001 01100111 01101111

RETURN













INDICE

  •  Anaconda
    • Error:  Failed to create Anaconda menus, Abort Retry Ignore (entrar)
  •  Android Studio
    • Implementando carácteres especiales en android studio (entrar)
    • Sobre las medidas trabajadas en programación (entrar)
    • Sobre android studio y como definir una interfaz (entrar)
  • Kotlin
    • Sobre Kotlin y sus variables (entrar)
  • PyCharm
    • Quitar la linea roja de corrección ortográfica en PyCharm (entrar)
    • nothing to show (entrar)
  • Web-Scraping
    • sobre Web Scraping (entrar)
    • Manejo de errores en Web Scraping (entrar)
    • LISTA DE USER AGENTS (entrar)
    • TypeError: 'Rule' object is not iterable (entrar)
  • Java
    • Programa simple java con comentarios (entrar)
    • Ejercitación Java Ejercicio 2 (entrar)
    • Ejercitación Java Ejercicio 3 (entrar)
  • BufferedReader (leer archivos .txt)
    • Programa simple 2, leer archivo .txt, uso de BufferedReader (entrar)
  • Linux
    • Ubuntu comandos utiles (entrar)
    • instalar paquetes por formato - linux (entrar)
  • Análisis de sistemas
    • Concepto de análisis de diseño de sistemas (entrar)
  • Atajos de teclado
  • Python  
    • La Biblioteca Estándar de Python (entrar)
  • PyQt5
    • PyQt5 - datos sobre ingreso de datos (entrar)
  • Git & Github
  • Qt Designer
    • programa simple - uso de SQLite (entrar)
    • QT Designer - aplicacion comentada PyQt5 (entrar)
    • usos de QDialog - ejemplo útil  (entrar)
  • Base de datos
    • Práctica de Base de Datos 1 (entrar)
  • SQLite3
    • Clave foránea en SQLite3 (entrar)
    • SQLite3 .help (entrar)
    • sql error sql logic error or missing database (entrar)
    • EXISTS (entrar)
  • Manejo de errores 
    • XAMPP - mysql_error.txt (entrar)
  • Webs de interés
  • .NET
    • Diferencias MVC y WebForms (entrar)
    • microsoft .net framework excepcion no controlada en la aplicacion (entrar)
  • Metodologias de desarrollo
    • TDD o Test-Driven Development (desarrollo dirigido por tests) (entrar)

  • SQL Server Management Studio 




01100110 01101001 01101110 00100000 01100100 01100101 00100000 01100011 01101111 01100100 01101001 01100111 01101111

RETURN




Quitar la linea roja de corrección ortográfica en PyCharm

 haces Ctl+Alt+S abris setting

ahi agregas español
luego haces clic en esa casilla y listo, no mas coso rojo molesto. FIN



RETURN



sobre Web Scraping

---------------------------------------------------------------------------------------------------------------

pip install requests ; para hacer requerimientos a un servidor

pip install beautifulsoup4 : para parcer los HTML

pip install lxml : para parcer los HTML

pip install selenium : para hacer extracciones dinámicas

pip install Pillow : para hacer extracciones de imágenes

pip install pymongo : para hacer guardado de información en base de datos

si hay problemas usar --user al final, da permisos de administrador, sudo para linux

pip install scrapy

---------------------------------------------------------------------------------------------------------------

tipos de web-scraping

nivel 1: tipo estático, donde toda la información permanece en una página web y no hay cargas del tipo dinámico.

librerías a usar:

  1. requests: para hacer requerimientos (pip install requests)
  2. xml y BeautifulSoup para parcear los requerimientos y extraer informacion
  3. scrapy para realizar requerimientos, parcearlos y extraer información
nivel 2: tipo estático con varias paginas con el mismo dominio, puede ser horizontal(llamado crollin horizontal) que es cuando tiene varias páginas en la parte inferior y se dirige a una página del mismo dominio y crollin vertical que es cuando de va accediendo al detalle de los elementos de la misma página.

librerías a usar:

  1. scrapy para realizar requerimientos, parcearlos y extraer información

nivel 3:tipo dinámico, donde se automatiza las acciones de un navegador (mediante python por ej) 

librerías a usar:

  1. Selenium python
nivel 4: usos de apis

nivel 5: donde se expande este mundo con
  • Autenticación
  • captchas
  • iFrames 

pasos a seguir para hacer web scraping 

  1. Se define una URL semilla, la pagina principal de donde se extraen los datos
  2. Realizar los requerimientos (requests)
  3. Obtener respuesta del servidor (en formato HTML)
  4. Se extrae la información deseada del HTML
  5. Se repite el paso 2 con otras URL del mismo dominio (dentro del crollin vertical/horizontal)

para el paso 4, como se extrae la información del HTML mediante XPATH
    XPATH: es un lenguaje que nos permite construir expresiones que recorren y procesan un documento XML. un HTML es un documento del tipo XML

al momento de armar un xpath se tienen en cuenta
  • los ejes (axis) da pie donde se realizará la búsqueda (ej: mediante // se busca en TODO el documento, con  / solo en la raíz y con ./ es una búsqueda relativa al lugar en el que se está)
  • el nodo de búsqueda (step) que es el nombre del tag del elemento en el que hacemos foco.
  • se definen los predicador, para pulir mas la búsqueda, por medio del usos de los atributos del tag, los atributos tienen un nombre y un valor  

ejemplo



para seleccionar page con el titulo matemáticas , puede hacerse mediante

//page[@title='Clase']/page[@title='2005']/page[@title='Matemáticas']
apretando shift y posando el mouse sobre la palabra sugiere...
//page[2]/page[2]/page[2]/@title 

el eje(axis) es el //, el nodo(step) el page y los predicados van dentro de [ ]  habiendo claro, muchas formas de construirlos. Se pueden indexar las búsquedas.

si van a la pagina de práctica y usan el siguiente código...
-------------------------------------- inicio codigo --------------------------------------
<app>
    <welcome-message>Hi! This is xpather beta...</welcome-message>
    <abstract>
        This web app enables you to query XML/HTML documents with your
browser in real time. It can generate queries for you too! 
    </abstract>
    <description>
        <subject>
You can enter your xpath query in the top-left panel 
and it will be instantly executed against this document.
Once some results are displayed on the right, you can 
scroll to them by clicking on them. 
</subject>
<subject>
To generate an xpath query for a specific element,
please hold CTRL and hover over it.
An xpath is generated heuristically with the aim
to be unambiguous and the shortest possible.
</subject>
    </description>
<extra-notes>
<note>
None of entered documents leave your computer because all
the processing is done by your powerful browser!
(of course as long as you do not save your input)
</note>
        <note>
This application is in an early beta version so please
be forgiving. XPath 2.0 is supported but namespaces are
still being added and they may not fully work yet. 
Please send your comments to: xpather.com@gmail.com
</note>
<note>
By default XML mode is used but if a document cannot
be parsed as XML then HTML mode kicks in.
</note>
<note>
Pasting documents bigger than 500kb may cause your
browser become sluggish or unresponsive.
</note>
</extra-notes>
</app>
-------------------------------------- fin codigo --------------------------------------
y quieren extraer el texto del último note pueden hacerlo mediante //note[last()]/text() acá se observa el uso de función como last() y text()
hay otros como...
position()=<numero>
contains(<tag(ej. @id)>,<cadena string(ej. "Matem")>) #si dentro de un tag contiene un tipo de cadena de string.
not # para negar un predicado
text() # extrae el texto

mas info en https://developer.mozilla.org/es/docs/Web/XPath/Functions (algunas entradas fallan)

webs de interés sobre xml y xpath

Probar expresiones en caliente
al apretar F12 podemos inspeccionar la pagina en la que estemos, en console podemos usar... 
$x("<expresion XPATH>")


mecanismos
teniendo...
import requests
from lxml import html

encabezados = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
}

url = "https://www.wikipedia.org/"

respuesta = requests.get(url, headers=encabezados)
requests = respuesta.text #solo lo convierte a texto plano
parser = html.fromstring(requests) #convierte el requests en un parceador, para extraer datos.
dato = parser.get_element_by_id("Matemática") # obtener elemento con id = "Matemática", entrega objeto de tipo elemento porque es una clase
dato_texto = dato.text_content() #para extrar el dato "Matemática" y poder imprimirlo, por ej.


# extraccion de datos usando beautifulSoup
import requests
from bs4 import BeautifulSoup

encabezados = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36"
}
# primer paso, definimos URL semilla
url = 'https://stackoverflow.com/questions'
respuesta = requests.get(url, headers=encabezados)
soup = BeautifulSoup(respuesta.text)
contenedor_de_preguntas = soup.find(id='questions')
lista_de_preguntas = contenedor_de_preguntas.find_all('div', class_='question-summary')
for pregunta in lista_de_preguntas:
titulo_pregunta = pregunta.find('h3').text
descripcion_pregunta = pregunta.find(class_='excerpt').text
descripcion_pregunta = descripcion_pregunta.replace('\n', '').replace('\r', '').strip()
soup.find() #busca según determinado parámetro
contenedor_de_preguntas.find_all() #busca todos los elementos que cumplan la función, entrega una lista.
se usa class_ porque class es una palabra reservada de python.
descripcion_pregunta.replace('\n', '').replace('\r', '').strip() #mediante estos códigos se limpia el resultado

INDICE