Python Headless Browser para GAE

Estoy intentando usar el lado del cliente de Angular.js con webapp2 en Google Appengine.

Para resolver los problemas de SEO, la idea era utilizar un navegador sin cabeza para ejecutar el lado del servidor de javascript y entregar el html resultante a los rastreadores.

¿Hay algún navegador sin cabeza para python que se ejecute en el motor de aplicaciones de Google?

Esto ahora se puede hacer en App Engine Flex con un tiempo de ejecución personalizado, por lo que estoy agregando esta respuesta ya que esta pregunta es lo primero que aparece en Google.

Basé este tiempo de ejecución personalizado en mi otro microservicio GAE flex que utiliza el tiempo de ejecución Python pre-construido

Estructura del proyecto:

webdrivers/ - geckodriver app.yaml Dockerfile main.py requirements.txt 

app.yaml:

 service: my-app-engine-service-name runtime: custom env: flex entrypoint: gunicorn -b :$PORT main:app --timeout 180 

Dockerfile:

 FROM gcr.io/google-appengine/python RUN apt-get update RUN apt-get install -y xvfb RUN apt-get install -y firefox LABEL python_version=python RUN virtualenv --no-download /env -p python ENV VIRTUAL_ENV /env ENV PATH /env/bin:$PATH ADD requirements.txt /app/ RUN pip install -r requirements.txt ADD . /app/ CMD exec gunicorn -b :$PORT main:app --timeout 180 

requisitos.txt:

 Flask==0.12.2 gunicorn==19.7.1 selenium==3.13.0 pyvirtualdisplay==0.2.1 

main.py

 import os import traceback from flask import Flask, jsonify, Response from selenium import webdriver from pyvirtualdisplay import Display app = Flask(__name__) # Add the webdrivers to the path os.environ['PATH'] += ':'+os.path.dirname(os.path.realpath(__file__))+"/webdrivers" @app.route('/') def hello(): return 'Hello!!' @app.route('/test/', methods=['GET']) def go_headless(): try: display = Display(visible=0, size=(1024, 768)) display.start() d = webdriver.Firefox() d.get("http://www.python.org") page_source = d.page_source.encode("utf-8") d.close() display.stop() return jsonify({'success': True, "result": page_source[:500]}) except Exception as e: print traceback.format_exc() return jsonify({'success': False, 'msg': str(e)}) if __name__ == '__main__': app.run(host='127.0.0.1', port=8080, debug=True) 

Descargue geckodriver desde aquí (linux 64):

https://github.com/mozilla/geckodriver/releases

Otras notas:

  • Tenga en cuenta las versiones de geckodriver, firefox y selenium que está utilizando, ya que puede ser finnickey, dando este error WebDriverException: Message: Can't load the profile. Possible firefox version mismatch. You must use GeckoDriver instead for Firefox 48+. Profile Dir: /tmp/tmp 48P If you specified a log_file in the FirefoxBinary constructor, check it for details. WebDriverException: Message: Can't load the profile. Possible firefox version mismatch. You must use GeckoDriver instead for Firefox 48+. Profile Dir: /tmp/tmp 48P If you specified a log_file in the FirefoxBinary constructor, check it for details.
  • A menos que esté utilizando geckodriver / firefox heredado, no configure DesiredCapabilities().FIREFOX["marionette"] = False https://github.com/SeleniumHQ/selenium/issues/5106
  • Se necesita display = Display(visible=0, size=(1024, 768)) para corregir este error: ¿Cómo arreglar Selenium WebDriverException: el navegador parece haber salido antes de poder conectarnos?

Para probar localmente:

 docker build . -t my-docker-image-tag docker run -p 8080:8080 --name=my-docker-container-name my-docker-image-tag 

Para desplegar en el motor de la aplicación:

 gcloud app deploy app.yaml --version dev --project my-app-engine-project-id 

Esa es una idea súper meta. Una solicitud web que está cumpliendo un servidor web que usa un navegador web sin cabeza para generar una página y devolver el resultado. Uf.

Eche un vistazo a la siguiente respuesta en navegadores sin cabeza, prestando especial atención a los basados ​​en Python.

pregunta de navegador sin cabeza : navegador de internet sin cabeza?

Parece que los que admiten Javascript utilizan WebKit y requieren PyQt o Pyside. Lo que significa que no podrá ejecutarlos en App Engine debido a las restricciones de tiempo de ejecución existentes.

Yo sugeriría, para fines de SEO, que haga algún tipo de detección de agente de usuario y emita una versión súper reducida de su página utilizando plantillas Jinja2 o algo así. De todos modos, probablemente obtendrías un mejor rendimiento.