antiblock-scrapy 0.0.1
Mecanismos antibloqueios para Scrapy
Requires Python: >=3.0

# antiblock-scrapy

Mecanismos antibloqueios para o Scrapy.

## Funcionalidades

Scrapy já vem com vários recursos antibloqueios que só precisam ser configurados, bem como muitos outros implementados por terceiros (alguns deles listados abaixo). 

Os recursos implementados foram:

- Rotacionador de user-agents
- Rotacionar de IPs via proxy Tor

## Instalação

Maneira mais fácil:

```bash
pip install antiblock-scrapy
```

## Instalação e configuração do Tor

É necessário configurar o **Tor**. Primeiramente, instale-o:

```bash
sudo apt-get install tor
```

Pare sua execução para realizar configurações:

```bash
sudo service tor stop
```

Abra seu arquivo de configuração como root, disponível em */etc/tor/torrc*, por exemplo, usando o nano:

```bash
sudo nano /etc/tor/torrc
```
Coloque as linhas abaixo e salve:

```
ControlPort 9051
CookieAuthentication 0
```

Reinicie o Tor:

```bash
sudo service tor start
```


É possível verificar o IP de sua máquina e comparar com o do Tor da seguinte forma:
- Para ver seu IP:
    ```bash
    curl http://icanhazip.com/
    ```
- Para ver o IP do TOR:
    ```bash
    torify curl http://icanhazip.com/   
    ```

Proxy do Tor não são suportados pelo Scrapy. Para contornar esse problema, é necessário o uso de um intermediário, nesse caso o **[Privoxy](https://www.privoxy.org/)**. 

> O servidor proxy do Tor se encontra, por padrão, no endereço 127.0.0.1:9050

### Instalação e configuração do **Privoxy**:
- Instalar: 
    ```bash
    sudo apt install privoxy
    ```
- Pare sua execução:
    ```bash
    sudo service privoxy stop
    ```
- Configurá-lo para usar Tor, abra seu arquivo de configuração:
    ```bash
    sudo nano /etc/privoxy/config
    ```
- Adicione as seguintes linhas:
    ```bash
    forward-socks5t / 127.0.0.1:9050 .
    ``` 
- Inicie-o: 
    ```
    service privoxy start
    ```

> Por padrão, privoxy executará no endereço 127.0.0.1:8118 

Teste: 
```bash
torify curl http://icanhazip.com/
```
```bash
curl -x 127.0.0.1:8118 http://icanhazip.com/
```
O IP mostrado nos dois passos acima deve ser o mesmo.

## Rotação de IPs via Tor

- Configure o middleware no arquivo de configuração de seu projeto (**settings.py**):
    ```python
    DOWNLOADER_MIDDLEWARES = {
        ...,
        'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,
        'antiblock_scrapy.middlewares.TorProxyMiddleware': 100
    }
    ```

- Habilite o uso da extensão:  
    ```python
    TOR_IPROTATOR_ENABLED = True
    TOR_IPROTATOR_CHANGE_AFTER = #número de requisições feitas em um mesmo endereço IP
    ```
Por padrão, um IP poderá ser reutilizado após 10 usos de outros. Esse valor pode ser alterado pela variável TOR_IPROTATOR_ALLOW_REUSE_IP_AFTER, como abaixo:

```python
TOR_IPROTATOR_ALLOW_REUSE_IP_AFTER = #
```

Um número grande demais pode tornar mais lento recuperar um novo IP para uso ou nem encontrar. Se o valor for 0, não haverá registro de IPs usados.

## Rotação de IPs via lista de proxies

Rotacionar IPs via Tor pode tornar o processo de coleta lento. Para isso existem ferramentas de terceiros que rotacionam uma lista de proxies dada, possivelmente deixando a coleta mais rápida (em comparação ao Tor), como:

- https://github.com/xiaowangwindow/scrapy-rotated-proxy
- https://github.com/TeamHG-Memex/scrapy-rotating-proxies

## Rotação de user-agents

- No arquivo de configuração de seu projeto Scrapy, adicione as seguintes linhas (**settings.py**):
    ```python
    DOWNLOADER_MIDDLEWARES = {
        ...,
        'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
        'antiblock_scrapy.middlewares.RotateUserAgentMiddleware': 500,
    }
    ```
- Defina a lista de user-agents, ative o módulo e defina um uso mínimo e máximo de cada user-agent (o uso de um user-agent será aleatório entre esses números) (**settings.py**):
    ```python
    USER_AGENTS = ['user-agent-1', 'user-agent-2',...,'user-agent-n']
    ROTATE_USER_AGENT_ENABLED = True
    MIN_USER_AGENT_USAGE = #uso mínimo de user-agent
    MAX_USER_AGENT_USAGE = #uso máximo de user-agent
    ```

- É possível conferir o user-agent usado no site: https://www.whatismybrowser.com/detect/what-is-my-user-agent 

## Atrasos entre requisições

Essa funcionalidade já é disponível por padrão ao Scrapy por meio de [DOWNLOAD_DELAY](https://docs.scrapy.org/en/latest/topics/settings.html#download-delay).

Por padrão:
- O valor de DOWNLOAD_DELAY é de 0.25 segundos
- O tempo entre requisições não é fixo, um valor entre 0.5 * DOWNLOAD_DELAY e 1.5 * DOWNLOAD_DELAY é escolhido entre cada requisição

Para alterar o atraso entre requisição, faça (em **settings.py**):

```python
DOWNLOAD_DELAY = # tem em segundos entre requisições
```

Para forçar que o tempo entre requisições seja fixo, ao contrário do padrão aleatório, faça (em **settings.py**):
```python
RANDOMIZE_DOWNLOAD_DELAY = False
```
### AutoThrottle

Uma opção mais avançada de colocar atrasos entre requisições é o [AutoThrottle](https://docs.scrapy.org/en/latest/topics/autothrottle.html#autothrottle-extension). Ela alterará a velocidade entre requisições de acordo com a latência de resposta do servidor e a capacidade de processamento da engine de maneira automática.  

Por padrão, essa configuração está desativada. Mas pode ser ativada por meio do seguinte comando (em **settings.py**):

```python
AUTOTHROTTLE_ENABLED = True
```

É necessário definir um delay inicial que será ajustado ao longo das requisições automaticamente. Defina-o por meio do comando abaixo, o default de 5.0 segundos (em **settings.py**):

```python
AUTOTHROTTLE_START_DELAY = #delay inicial  
```

Defina também um delay máximo, o default de 60.0 segundos (em **settings.py**):

```python
AUTOTHROTTLE_MAX_DELAY = #delay máximo
```

O atraso das próximas requisições será ajustado para um valor respeitando DOWNLOAD_DELAY e AUTOTHROTTLE_MAX_DELAY, levando em conta a média de requisições paralelas enviadas ao servidor que, por padrão, é 1.0. Esse valor pode ser ajustado pelo comando abaixo (em **settings.py**): 

```python
AUTOTHROTTLE_TARGET_CONCURRENCY = #média de requisições concorrentes
```

Mais detalhes podem ser encontrados [aqui](https://docs.scrapy.org/en/latest/topics/autothrottle.html#throttling-algorithm).

## Gerenciamento de cookies

Scrapy já possui mecanismos de gerencialmente de cookies e detalhes podem ser encontrados [aqui](https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#module-scrapy.downloadermiddlewares.cookies).

Por exemplo, caso possua os cookies de acesso de um site que é necessário login, uma das possíveis abordagens é criar um Spider como o abaixo:

```python

import scrapy

# Cookies de login di site
COOKIES = [{},..., {}]

class LoginSpider(scrapy.Spider):
    name = 'foo'

    def start_requests(self):
        urls = ['site-com-login-1', 'site-com-login-2', ..., 'site-com-login-n']
        for url in urls:
            yield scrapy.Request(url='site-que-precisa-login', cookies=COOKIES, callback=self.parse)

    def parse(self, response):
        ...
```

Outras formas de lidar como cookies como, por exemplo, cada requisição com seu próprio cookie, podem ser feitas usando **cookiejar**, mais detalhes [aqui](https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#module-scrapy.downloadermiddlewares.cookies). 

Bibliotecas de terceiros permitem **persistência de cookies** e outros recursos, como [scrapy-cookies](https://scrapy-cookies.readthedocs.io/en/latest/intro/overview.html).