- Python 3.9 - 3.11 (python-pip, python-dev)
- Docker
- PostgreSQL. Возможен запуск PostgresSQL в Docker
- Для работы Telegram bot необходимо создать бота и получить bot token
Клонировать репозиторий:
git clone [email protected]:ecodomen/nsreg-watcher.git
Перейти в директорию проекта:
cd nsreg-watcher
Создать виртуальное окружение.
- Если версии Python, установленная в системе по умолчанию, соответствует требованиям, выполнить:
python3 -m venv env
- или указать версию Python явно:
python3.11 -m venv env
Активировать виртуальное окружение:
source env/bin/activate
Обновить pip:
pip install pip -U
Установить зависимости:
pip install -r requirements.txt
В корневой директории проекта создать файл .env
и заполнить его по шаблону .env.template
-
Использование локальной СУБД PostgreSQL.
- Создать базу данных:
createdb -U postgres -h localhost -p 5432 nsreg
-
Запуск PostgresSQL в Docker.
- Экспортировать переменные окружения:
export $(echo $(cat .env | sed 's/#.*//g'| xargs) | envsubst)
- выполнить запуск сервисов:
sudo docker compose up -d
Выполнить миграции:
python src/website/manage.py migrate
Запустить dev сервер Django:
python src/website/manage.py runserver
В новом окне терминала перейти в директорию проекта:
cd <PATH>/nsreg-watcher
Проверить и при необходимости задать права -rwxrwxr-x
на выполнение runspiders.sh
:
ls -l runspiders.sh
chmod 775 runspiders.sh
Выполнить скрипт для запуска scrapy:
./runspiders.sh
Дождаться завершения парсинга.
В папке нужно создать новый парсер с обязательным нэймингом "nsreg_sitename"
Посмотрите пример парсера с использованием композиции:
По аналогии пишете имена, ссылки в классе вашего Спайдера. site_name нужно найти на сайте регистратора:
class NsregDomainshopSpider(scrapy.Spider):
name = "nsreg_domainshop.py"
start_urls = ["https://domainshop.ru/services/"]
allowed_domains = ("domainshop.ru")
site_names = ("ООО «Лавка доменов»",)
Подбираете путь к ценам: покупка домена, продление, перенос. Например:
'price_reg': '/html/body/div/div[2]/div/div/div/div/div[3]/div/div/div/div/table/tbody/tr[1]/td[2]/div/text()'
Пути можно посмотреть на сайте и скопировать. Могут возникнуть проблемы с тем, что скопированный путь неправильный -- тогда нужно исследовать его самому
Подбираете регулярное выражение (поможет сайт Regex):
regex=r"([0-9]+[.,\s])?руб"
# -*- coding: utf-8 -*-
import scrapy
from ..base_site_spider import BaseSpiderComponent
# Пример спайдера для одного сайта
class NsregDomainshopSpider(scrapy.Spider):
name = "nsreg_domainshop.py"
start_urls = ["https://domainshop.ru/services/"]
allowed_domains = ("domainshop.ru")
# в site_names важно поставить запятую, иначе scrapy вместо целого названия вставит одну букву
site_names = ("ООО «Лавка доменов»",)
def __init__(self, name=None, **kwargs):
super().__init__(name, **kwargs)
self.component = BaseSpiderComponent(
start_urls=self.start_urls,
allowed_domains=self.allowed_domains,
site_names=self.site_names,
regex=r"([0-9]+[.,\s])?руб",
path={
'price_reg': '/html/body/div/div[2]/div/div/div/div/div[3]/div/div/div/div/table/tbody/tr[1]/td[2]/div/text()',
'price_prolong': '/html/body/div/div[2]/div/div/div/div/div[3]/div/div/div/div/table/tbody/tr[4]/td[2]/div/p/text()',
'price_change': '/html/body/div/div[2]/div/div/div/div/div[3]/div/div/div/div/table/tbody/tr[7]/td[2]/div/text()'
}
)
# Метод для обработки ответов на запросы
def parse(self, response):
# Применение метода parse компонента BaseSpiderComponent
return self.component.parse(response)
Если вам требуется добавить разные регулярные выражения для каждого из полей, то в поле regex записывается такой dict:
regex = {
'price_reg': 'your_regex1',
'price_prolong': 'your_regex2',
'price_change': 'your_regex3'
}
В сложных случаях, когда требуется пройтись по разным страницам внутри сайта, вам необходимо переписать функцию parse. Для прохода по разным страницам лучше всего добавить соответствующую функцию:
from nsreg.items import NsregItem()
EMPTY_PRICE = {
'price_reg': None,
'price_prolong': None,
'price_change': None,
}
...
def parse_price_change(self, response):
price_change = response.xpath(self.component.path['price_change']).get()
price_change = find_price(, price_change)
item = NsregItem()
item['name'] = "ООО «Ваш ООО»"
price = item.get('price', EMPTY_PRICE)
price['price_change'] = price_change
item['price'] = price
price['price_change'] = price_change
item['price'] = price
yield item
А также вызвать ее из функции parse:
def parse(self, response):
price_reg = response.xpath(self.pathreg).get()
price_reg = self.find_price(self.regex_reg, price_reg)
price_prolong = response.xpath(self.pathprolong).get()
price_prolong = self.find_price(self.regex_prolong, price_prolong)
yield scrapy.Request('https://2domains.ru/domains/transfer', callback=self.parse_price_change)
site_name = self.site_names[0]
item = NsregItem()
item['name'] = site_name
price = item.get('price', EMPTY_PRICE)
price['price_reg'] = price_reg
price['price_change'] = price_change
item['price'] = price