Giter Club home page Giter Club logo

dev-job-analytics's Introduction

👋 About Me

Hello, my name is Diego Palma, and I am kind of a software developer. I am from Chile and I ❤️ open-source. I hold an M.Sc in Computer Science from University of Concepción and during this masters, I worked mainly on Natural Language Processing (NLP). Actually, a product from my thesis was the paper Coherence-Based Automatic Essay Assessment.

I strongly believe that education should be available for everyone, and one of my goals is to contribute to education in the reading comprehension field. I created TRUNAJOD which is an open-source library for text-complexity assessment.

📫 Social Media

💻 Open Source Work Stats

Diego Palma github stats

dev-job-analytics's People

Contributors

diekrul avatar dpalmasan avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

diekrul

dev-job-analytics's Issues

Actualizar README general y componentes

Para el README.md general estaría bueno poner gifs, o una vista más dinámica de la aplicación. Lo mismo para los componentes:

  • jobservatory_express
  • jobservatory_react
  • scrapper

Agregar más documentación de uso, y ejemplos.

Script para crear respaldo diario de la base de datos

  • Ayer 2021-09-01 tuvimos un incidente intentando eliminar algunos documentos inválidos de la DB
  • Por error se perdieron todos los datos de la colección scrapeada desde linkedin

Debemos crear un job que respalde la DB de forma diaria.

Aumentar coverage de backend a 85%

Actualmente el coverage está bajo el umbral que se decidió por acuerdo. Se deben crear tests de manera de aumentar el coverage al umbral esperado. También se debe actualizar el package.json:

"scripts": {
    "start": "node index",
    "server": "nodemon index",
    "test": "nyc --check-coverage --lines 75 mocha tests",
    "client": "npm start --prefix ./../jobservatory",
    "dev": "concurrently \"npm run server\" \"npm run client\"",
    "linter": "eslint . --ext .js,.jsx,.ts,.tsx"
  },

Se debe actualizar --lines 75 a --lines 85.

Agregar cache para requests

Podríamos considerar redis, ya que sabemos que los datos se actualizan diariamente, no tiene sentido hacer llamadas a la DB cada vez que pedimos datos si ya sabemos que estará en cache. Esto involucrará actualizar los endpoint del backend.

Hacer refactor a uso de `moment`

Tenemos varias funciones del backend que usan moment, lo que convierte a las funciones en no idempotentes. Idealmente, deberíamos hacer la fecha una entrada a estas funciones.

[MVP] Modelo de datos y documentación

Para el MVP tenemos que tener claro el modelo de datos, ya que el scrapper alimentará la base de datos y por lo tanto hay que tener los schemas definidos, además de agregar a la documentación del proyecto (en gdrive) el modelo de datos a utilizar.

Ya existe un mock de datos del cual el frontend está basado:

https://github.com/dpalmasan/dev-job-analytics/blob/main/jobservatory_react/src/fakeFinalData.js

Por lo que hay que agregar la lógica de ingesta de datos a la BBDD basado en este prototipo y completar la documentación.

Actualizar LoggedIn Scraper para aceptar un driver de Selenium con opciones

En el deployment a heroku, me di cuenta que es mejor tener la posibilidad de agregar un driver de selenium con opciones, por ejemplo:

class LoggedLinkedinScrapper(LinkedinScraper):
    """Implement a LinkedinScraper using identity."""

    def __init__(
        self,
        email: str,
        password: str,
        driver: Optional[webdriver.chrome.webdriver.WebDriver] = None,
    ):
        """Start ``selenium`` driver to scrap from the web.

        :param email: Email to login into Linkedin
        :type email: str
        :param password: Password
        :type password: str
        """
        self.driver = driver
        if self.driver is None:
            self.driver = webdriver.Chrome(ChromeDriverManager().install())
        self.email = email
        self.password = password
        self.logged = False

De esta forma se puede hacer algo como:

chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = os.environ.get("GOOGLE_CHROME_BIN")
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--no-sandbox")
driver = webdriver.Chrome(
    executable_path=os.environ.get("CHROMEDRIVER_PATH"),
    chrome_options=chrome_options,
)
sc = LoggedLinkedinScrapper(EMAIL, PASSWORD, driver)

Crear tests para backend

Por completitud, deberíamos tener tests para todo el código. Este ticket es para implementar tests en el backend. Probablemente utilizaremos mocha.

Agregar pipeline CI para frontend (test + coverage)

El scraper y el backend tienen sus suite de pruebas, y pipeline CI configurado. Sólo queda setear CI en el frontend. Ya que @Diekrul quieres aprender sobre esto, te recomiendo tomar este issue.

Requerimientos

  • Suite de pruebas creadas para el frontend
  • Script creado para ejecutar pruebas (ej: yarn test)
  • Pipeline CI configurado (si quieres probar en local puedes usar esta herramienta https://github.com/nektos/act; Ojo que necesita tener Docker instalado).
  • Agregar chequeos de coverage a las pruebas (y definir un umbral, por ejemplo 85%)

Implementar Scrapper con inicio de sesión

Para un scrapping adhoc, se puede utilizar Selenium para extraer el conteo de puestos teniendo sesión iniciada, por ejemplo el siguiente snippet:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager


  
VERIFY_LOGIN_ID = "global-nav-search"
REMEMBER_PROMPT = 'remember-me-prompt__form-primary'

driver = webdriver.Chrome(ChromeDriverManager().install())
email = "EMAIL"
password = "PASSWORD"

driver.get("https://www.linkedin.com/login")
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "username")))
email_elem = driver.find_element_by_id("username")
email_elem.send_keys(email)

password_elem = driver.find_element_by_id("password")
password_elem.send_keys(password)
password_elem.submit()

driver.get("https://www.linkedin.com/jobs/search/?geoId=92000000&keywords=React.js&location=Todo%20el%20mundo")
element = driver.find_element_by_tag_name("small")
print(element.text)

Se puede implementar una clase nueva, algo como LoggedInLinkedinScrapper para extraer estos resultados.

Agregar URI del backend a configuración

Actualmente, la URI del backend está hardcodeada en el frontend. Para el release, idealmente deberíamos tener esta URI en el archivo de configuración, ya que es una parte de la configuración, por ejemplo:

https://github.com/dpalmasan/dev-job-analytics/blob/main/jobservatory_react/src/components/detail/Detail.tsx#L37

Lo ideal sería quitar la URI harcodeada y hacerla parte de una configuración. Lo único fijo en la URI sería la API (el host y el puerto deberían ser parte de la configuración por ahora)

Agregar chequeos de coverage (frontend, backend, scraper)

Idealmente, queremos tener la mayoría del código cubierto por casos de prueba. Inicialmente, deberíamos apuntar a un coverage de un 85% (ideal 100%). Agregar a los linters chequeos de coverage:

  • scraper (pytest-cov)
  • backend (mocha)
  • frontend (tengo entendido que aún no tenemos tests para esto)

Actualizar script get_data para usar uri personalizada en la conexión con MongoDB

Actualmente tenemos esto:

def main():
    """Entry point."""
    connect("jobservatory-manual")
    with open("jobserver-config.yaml", "r") as fp:
        creds = yaml.safe_load(fp)

    sc = LoggedLinkedinScrapper(creds["email"], creds["password"])
    import_data(
        sc,
        [
            "React.js",
            "Angular.js",
            "Ruby on Rails",
            "Java",
            "Python",
            "Data Engineer",
        ],
        0,
    )

Pero sería mejor actualizar el jobserver-config.yaml con la opción de tener una URI personalizada y conectar a cualquier DB (local o remota)

Investigar como automatizar scripts de ingesta de datos

El script backfill_so_data es fácil de automatizar porque hace un simple request sin autorización. El script problemático es el scraper de linkedin, ya que requiere logearse desde la máquina. Idea, apuntar display a una máquina local y logearse.

chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = os.environ.get("GOOGLE_CHROME_BIN")
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--no-sandbox")
driver = webdriver.Chrome(
    executable_path=os.environ.get("CHROMEDRIVER_PATH"),
    chrome_options=chrome_options,
)

Crear scrapper de datos de linkedin

El scrapper debe estar conectado con la Base de Datos y debe ejecutarse en un período determinado para actualizar la base de datos.

El link funciona de esta forma
https://www.linkedin.com/jobs/search/?geoId=92000000&keywords=React.js&location=Todo%20el%20mundo

Ahi se saca el dato de todo el mundo de la tecnologia React.js (se puede hacer con navegador incognito no necesita sesion)

Screen Shot 2021-08-03 at 12 41 08 PM

La forma en la que creo que serviria recibir desde el front, sigue este patron.

https://github.com/dpalmasan/dev-job-analytics/blob/main/jobservatory_react/src/fakeFinalData.js

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.