{"id":18679986,"url":"https://github.com/effeix/krawler","last_synced_at":"2025-10-06T13:03:19.452Z","repository":{"id":92510057,"uuid":"153927872","full_name":"effeix/krawler","owner":"effeix","description":null,"archived":false,"fork":false,"pushed_at":"2018-12-10T02:48:55.000Z","size":52,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-27T22:22:25.545Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/effeix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-20T16:57:14.000Z","updated_at":"2018-12-10T02:48:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"82848015-50be-48d1-b963-830743c74891","html_url":"https://github.com/effeix/krawler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effeix%2Fkrawler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effeix%2Fkrawler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effeix%2Fkrawler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effeix%2Fkrawler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/effeix","download_url":"https://codeload.github.com/effeix/krawler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239533067,"owners_count":19654617,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T09:47:28.212Z","updated_at":"2025-10-06T13:03:14.405Z","avatar_url":"https://github.com/effeix.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# krawler\n\n## Objetivo\nUm *Web Crawler* tem como objetivo recuperar informações de uma ou mais páginas web de maneira inteligente, percorrendo caminhos criados pelos links de cada página. Neste projeto, o objetivo é criar um [Web Crawler](https://en.wikipedia.org/wiki/Web_crawler) capaz de recuperar informações de produtos disponíveis em sites de e-commerce e disponibilizá-las para o usuário, semelhante ao funcionamento do site [Buscapé](https://www.buscape.com.br/). Este *crawler* deve ser implementado de maneira paralela, afim de diminuir o tempo de execução do programa, criando assim um sistema amigável para o usuário.\n\nA biblioteca PThread será utilizada para realizar esta implementação paralela. A paralelização do programa se dá por meio da utilização de diversas threads e troca de dados entre estas threads, ações facilitadas pela biblioteca. O intuito deste tipo de implementação é permitir a execução mais rápida do programa\n\nAo final da execução, o programa deve imprimir no terminal os produtos buscados no seguinte formato:\n\n```json\n{\n    \"nome\": \"\",\n    \"descricao\": \"\",\n    \"foto\": \"\",\n    \"preco\": 0,\n    \"preco_parcelado\": 0,\n    \"preco_num_parcelas\": 0,\n    \"categoria\": \"\",\n    \"url\": \"\"\n}\n```\n\n## Utilização\nPrimeiramente, deve-se compilar o projeto. Na raíz do repositório, crie uma pasta de nome `build/`, ficando com a seguinte árvore:\n```sh\n$ mkdir krawler/build/\n```\n\n```\nkrawler/\n    krawler/\n        build/\n        ....\n    ...\n```\n\nEm seguida, vá para a pasta `build/`\n```sh\n$ cd build/\n```\n\nPor fim, realize a compilação:\n```sh\n$ cmake ..\n$ make -j4\n```\n\nUm executável será criado dentro da pasta `build/`, de nome `krawler`.\n\nO projeto possui apenas um executável, capaz de executar a versão sequencial ou paralela de acordo com o desejo do usuário. Existem quatro variáveis de ambiente a serem definidas antes da execução do programa:\n\n| Variável \t| Descrição                                                     \t| Padrão \t|\n|:--------:\t|---------------------------------------------------------------\t|--------\t|\n|    URL   \t| URL de uma categoria de site de E-Commerce                    \t| nulo   \t|\n|   MODE   \t| Modo de execução. \"seq\" para sequencial e \"par\" para paralelo \t| seq    \t|\n|  N_PROD  \t| Quantidade de threads produtoras para o modo paralelo         \t| 2      \t|\n|  N_CONS  \t| Quantidade de threads consumidoras para o modo paralelo       \t| 2      \t|\n\n#### Sites suportados\n- [Magazine Luiza](https://www.magazineluiza.com.br/)\n\nO programa utiliza categorias de produtos como entrada. A categoria é uma URL de um site suportado. No caso do Magazine Luiza, a URL deve ser obtida navegando para o site, clicando em **Todos os Departamentos** na parte superior esquerda, e escolhendo um dos links destacados pela área vermelha:\n\n\u003cimg src=\"https://i.imgur.com/ief76w1.png\" alt=\"\" width=\"50%\" height=\"50%\" /\u003e\n\nNa próxima página clique em um dos links destacados novamente pela área vermelha:\n\n\u003cimg src=\"https://i.imgur.com/FNuQU2P.png\" alt=\"\" width=\"50%\" height=\"50%\" /\u003e\n\nA URL da págna que abrirá é a que deve ser utilizada:\n\n\u003cimg src=\"https://i.imgur.com/NmOzgTQ.png\" alt=\"\" width=\"50%\" height=\"50%\" /\u003e\n\nO teste acima foi realizado clicando em: **Todos os Departamentos \u003e Celulares \u003e Smartphones** obtendo a URL **https://www.magazineluiza.com.br/smartphone/celulares-e-smartphones/s/te/tcsp/**\n\nA URL precisa ser definida, senão o programa não executará e mostrará uma mensagem de erro. No modo sequencial, as variáveis N_PROD e N_CONS são ignoradas. É possível definir N_PROD e N_CONS como 0, mas causarará comportamento inesperado.\n\nExemplo de utilização sequencial:\n```sh\n$ URL=https://www.magazineluiza.com.br/smartphone/celulares-e-smartphones/s/te/tcsp/ MODE=seq ./krawler\n```\n\nExemplo de utilização paralela:\n```sh\n$ URL=https://www.magazineluiza.com.br/smartphone/celulares-e-smartphones/s/te/tcsp/ MODE=par N_PROD=4 N_CONS=4 ./krawler\n```\n\n## Dependências\n- libcurl\n- Boost\n- PThreads\n\n## Funcionamento\n### Versão sequencial\nEsta versão é bastante simples. Primeiramente é coletada a URL do usuário e feito o download do HTML da página. Por meio do uso de *regex*, é possível obter outras páginas de produtos da mesma categoria. As diversas páginas de produtos são baixadas e, novamente utilizando *regex*, as informações dos produtos montadas de acordo com a visualização mencionada na introdução.\n\n### Versão paralela\nJá a versão paralela é um pouco mais complexa. Para este projeto foi escolhida a implementação do modelo Produtor-Consumidor, em que diversas threads são criadas, algumas como produtoras e outra como consumidoras. As threads produtoras estão encarregadas de realizar os downloads das diversas páginas e guardar este conteúdo em uma fila, enquanto as threads consumidoras coletam o conteúdo do download e aplicam as regras em *regex* para obter as informações desejadas. No final, as threads consumidoras imprimem cada produto no terminal.\n\nA sincronização entre threads é realizada com a utilização de semáforos, que bloqueiam ou liberam o acesso à fila de tarefas (URLs) a serem cumpridas.\n\n## Testes\nURL: https://www.magazineluiza.com.br/agendas-e-diarios/papelaria/s/pa/pagd/ (568 produtos)\n### Hardware\n- Intel i7-4510U\n- 8GB RAM\n- Ubuntu 18.04\n- Dell Inspiron 5447\n- 4 núcleos (2 virtuais)\n\n### Métricas\n\nAfim de explorar a performance deste programa, algumas métricas de tempo são coletadas ao longo do *crawling*. São elas:\n\n- Tempo ocioso (TOTAL_IDLE_TIME): tempo de espera pelo download de páginas\n- Tempo por produto (PROD_TIME): tempo gasto para baixar uma página específica de um produto e criar sua visualização em JSON. Cada produto baixado possui uma linha com o tempo gasto.\n- Tempo médio por produto (AVG_TIME_PER_PRODUCT): tempo total de execução dividido pelo número de produtos coletados.\n\n\nTodas as métricas são enviadas para a saída de erro padrão do sistema, que pode ser redirecionada para um arquivo de texto a gosto do usuário, como no exemplo a seguir (todos os valores estão em segundos):\n\n```\n1.2\n0.85\n0.50\n...\nTOTAL_IDLE_TIME: 180\nAVG_TIME_PER_PRODUCT: 0.7\n```\n\n### Resultados\nForam realizados testes utilizando as versões sequenciais e paralelas, sendo a segunda testada três vezes: 1) 3 threads produtoras e 1 consumidora; 2) 2 produtoras e 2 consumidoras; 3) 1 produtora e 3 consumidoras. Como o computador utilizado para testes possui apenas 4 núcleos, uma execução com mais threads causaria troca de contexto entre threads, o que não é interessante para o estudo dos tempos de execução do programa. Os valores de tempo ocioso para a implementação paralela são ambíguos, pois apresentam uma soma do tempo total, sendo que downloads esto sendo feitos paralelamente. Assim, o tempo foi dividido por 4, para bter uma média do tempo de download por thread.\n\n| Tempos (s)          | Sequencial | Paralela (1) | Paralela (2) | Paralela (3) |\n|:--------------------:|------------|--------------|--------------|--------------|\n| TOTAL_IDLE_TIME      | 638.904    | 228.385      | 238.122      | 241.005      |\n| AVG_TIME_PER_PRODUCT | 1.56       | 0.74         | 0.94         | 0.97         |\n\nForam analisados também os consumos de memória para a versão sequencial e a versão paralela 2, utilizando a biblioteca mprof (em python) como a seguir:\n\n```sh\nmprof run URL=https://www.magazineluiza.com.br/agendas-e-diarios/papelaria/s/pa/pagd/ MODE=seq ./krawler\n```\ne\n```sh\nmprof run URL=https://www.magazineluiza.com.br/agendas-e-diarios/papelaria/s/pa/pagd/ MODE=par N_PROD=2 N_CONS=2 ./krawler\n```\nOs resultados podem ser vistos com:\n```sh\nmprof plot\n```\nEm seguida, limpe a análise com:\n```sh\nmprof clean\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feffeix%2Fkrawler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feffeix%2Fkrawler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feffeix%2Fkrawler/lists"}