Um tempo atrás, escrevi um pouco sobre como tinha realizado uma contribuição para coletar os diários oficiais de Americana. Porém, tem alguns erros e imprecisões por lá e recomendo a leitura apenas para caráter informativo. Se você quiser seguir algo, este está com certeza melhor e é para a cidade de Araraquara!

Preparando o terreno

Fork do projeto

Entre no seu github e clique para fazer fork do projeto, depois disso acesse seu perfil e copie o link do seu fork, deve estar algo assim:

https://github.com/SEU_NOME_DE_USUARIO/querido-diario

Clonando o projeto

É necessário instalar o git antes! Depois de realizar o fork, agora podemos puxar os dados para a nossa máquina, para isso use o comando:

git clone https://github.com/SEU_NOME_DE_USUARIO/querido-diario

Depois disso, o projeto foi clonado para seu computador, sendo assim, temos boa parte do ambiente necessário.

Agora, vamos criar um ramo dentro do nosso projeto, para que possamos separar o código e não fazer bagunça, para isso usamos o comando:

git checkout -b spider-to-palmas

Deste modo, estamos criando um ramo que terá o nosso código para a spider que queremos criar, tendo como base o código no ramo principal. Para listar todos os ramos e ver onde estamos:

git branch -a

Configurando Python

É necessário [instalar o Python no Windows]! Na maioria das distribuições Linux, vem instalado por padrão. Precisamos criar nosso ambiente virtual no python, para garantir que nosso sistema operacional não seja afetado pelas bibliotecas que vamos instalar:

pip3 install virtualenv
virtualenv --python=python3.9 venv
source venv/bin/activate

Agora com nosso ambiente criado e ativo (deve ter aparecido venv do lado esquerdo no seu terminal), agora podemos instalar os requerimentos do projeto, navegue até o arquivo requirements.txt.

pip install -r requirements.txt

Depois disso, você tem o ambiente completo configurado no seu computador, podendo executar qualquer spider existente no projeto. Se você for até o diretório das spiders, poderá encontrar um punhado delas!

cd querido-diario/data_collection/gazette/spiders

Agora podemos executar por exemplo, a spider da cidade de Jaú, do Estado de São Paulo:

scrapy crawl sp_jau

Com esse comando, a spider será executada e todos os diários oficiais da cidade serão baixados no seu computador, hoje (16 de agosto de 2022) ela está funcinal. Mas além de executar, a ideia é criar uma spider nova, então notei no arquivo CITIES.md, que tem todas as cidades e as spiders existentes, que faltam muitas cidades. Peguei uma lista das 200 maiores cidades do Estado de SP e filtrei as que estavam faltando. A cidade de Araraquara é uma delas! Vamos fazer :)

Criando a spider

spider

Para criar nossa spider, basta usar o recurso do próprio Scrapy, ele já cria um modelo legal:

scrapy genspider sp_araraquara diariooficial.americana.sp.gov.br

Depois disso, você pode abrir o arquivo gerado com seu editor de texto preferido, no meu caso, vou utilizar o Vim.

vim sp_araraquara.py

Você irá se deparar com um arquivo contendo uma configuração básica, vamos alterá-lo um pouco.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import datetime
from urllib.parse import urlencode

import dateparser

from gazette.items import Gazette
from gazette.spiders.base import BaseGazetteSpider


class SpAraraquaraSpider(BaseGazetteSpider):
    TERRITORY_ID = "3503208"
    name = "sp_araraquara"
    allowed_domains = ["diariooficialcmararaquara.sp.gov.br"]
    start_date = datetime.date(2021, 3, 4)  # First gazette available
    end_date = datetime.datetime.today()
    start_urls = ["https://www.diariooficialcmararaquara.sp.gov.br"]
    search_url = "https://www.diariooficialcmararaquara.sp.gov.br/diario/busca?"
    base_url = "https://www.diariooficialcmararaquara.sp.gov.br"

    def parse(self, response):
        pass

Explicação

Linha 1 a 7: estamos importando diversas bibliotecas, referentes à manipulação de hora, bibliotecas com recursos padronizados para utilizar o Scrapy no projeto e outras;

Linha 10: é declarada a classe SpAraraquaraSpider e entre parênteses é informado que ela herda a classe BaseGazetteSpider;

Linhas 11: Define o código IBGE da cidade

Linha 12: Define o nome da nossa spider;

Linha 13: Define o domínio permitido, muito útil para garantir que nada sairá de controle;

Linhas 14 e 15: Configura o primeiro dia que foi publicado diário oficial da cidade e depois a data atual

Linha 16: Define onde nossa spider vai começar sua atuação;

Linha 17 e 18: Determina a URL que é realizada a pesquisa do diário e uma base para realizarmos os downloads

Linha 20: Criado o método parse, o qual recebe o objeto response. O objeto response contem inclusive o código fonte da página atual que a spider está;

Criando a Spider

Investigação

Acesse o site dos diários de Araraquara e pressione F12, vai aparecer um painel e lá tem uma seção de Rede, onde é possível ver (quase) todas as mensagem que seu navegador trocou com o site alvo.

imagem1

No formulário à esquerda, tem como filtrar por datas, após colocar a data, clique em buscar. Podemos encontrar esta requisição:

imagem1

Assim descobrimos que podemos interagir diretamente com a URL!

Desenvolvendo o método parse

Depois de alterarmos nosso arquivo base, agora devemos criar o método parse, o qual é o ponto de retorno padrão quando outros métodos não definem o callback, por isso este acaba sendo responsável também por nutrir nossa classe com links!

1
2
3
4
5
6
7
8
9
10
11
12
def parse(self, response):
        initial = self.start_date.strftime("%d/%m/%Y")
        end = self.end_date.strftime("%d/%m/%Y")

        params = {
            "data": initial,
            "dataFinal": end,
            "descricao": "",
            "subcategoria": "",
        }
        url_params = urlencode(params)
        yield response.follow(f"{self.search_url}{url_params}", self.parse_gazette)

Explicação

Linha 2 e 3: Definimos as datas de início e fim no formato de string;

Linha 5: Configuramos os parâmetros que o site passa via requisição na URL;

Linha 11: codificamos as informações para serem passadas na URL;

Linha 12: Usando o yield fazemos com que o comando seguinte entre para a fila de processamento e chama o método parse_gazette

Desenvolvendo o método parse_gazette

Depois de realizar a requisição com os parâmetros que passamos via URL, agora vamos extrair os dados que retornaram e salvar os diários.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def parse_gazette(self, response):

        gazettes = response.css(".event-card.animated.flipInX")

        for gazette in gazettes:
            card = gazette.css(".event-card")

            edition_number = card.css(".event-data h4 ::text").re_first(r"[0-9]+")
            date = card.re_first(r"[0-9]+/[0-9]+/[0-9]+")
            date = datetime.datetime.strptime(date, "%d/%m/%Y").date()
            url = card.css(".row ::attr(href)").get()
            url = self.base_url + url
            if card.css(".event-edicao p ::text").get() == "Edição Única":
                extra_edition = False
            else:
                extra_edition = True

            yield Gazette(
                date=date,
                file_urls=[url],
                is_extra_edition=extra_edition,
                power="executive",
                edition_number=edition_number,
            )

Explicação

Linha 3: com este comando, extraímos o elemento da página Web utilizando os seletores de CSS, utilizamos o nome da classe do objeto para isso. Para encontrar essa informação, basta usar o botão F12 e procurar o elemento no código HTML e então jogamos essa informação na variável card que utilizaremos depois.

imagem1

Linhas 5: Com este for vamos passar por todos os elementos Web que encontramos

Linha 6 a 12: Navegamos utilizando o CSS, utiliza-se Regex para extrair as informações necessárias para o diário oficial

Linha 18: Damos início à criação do nosso objeto a ser inserido no projeto, estruturando a informação no modelo do projeto, o yield adiciona isso à fila de processamento e segue realizando downloads.

Subindo o código

Precisamos dizer ao git que iremos adicionar os arquivos alterados:

git add .

Damos início ao nosso commit:

git commit -m "Add spider Araraquara/SP"

Subimos nosso código para o repositório:

git push

comemoracao

Depois de fazer tudo isso, ao entrar na página do GitHub, vai aparecer o botão para realizar o Pull Request, isso encerra uma contribuição com o projeto. Se você tiver interesse em contribuir ou quiser conversar sobre, basta abrir um issue na página do GitHub do projeto.

Conclusões

Contribuindo com a extração da cidade de Americana, pude aprender bastante sobre a linguagem Python e também sobre Scrapy, quando expomos nosso código publicamente a comunidade nos ajuda a realizar o melhor. Algo que já foi aplicado na coleta da cidade de Araraquara.

Espero que este relato tenha sido útil e ajudado você que está iniciando no Scraping!