click fraud detection
click fraud detection
Blog Case

Домены с истекающим сроком

BLOG
CASE
185
0
5/ 5stars
5/5

Недавно от “насяльника” мне поступила такая задача:

Димыч скажи пож, вот отсюда - https://www.reg.ru/domain/deleted/?&free_from=07.06.2019&free_to=07.06.2019&order=ASC&sort_field=dname_idn%20%20%20%20&page=5 можно сграбить названия доменов?

Я зашел по ссылке, увидел список доменов у которых истекает срок, постраничную навигацию и все дела.

Я подумал “Почему бы и нет?” буду пробегать по постраничке, меняя параметр page=1,2,3 в урле, парсить страницы и сохранять домены.

Что может быть проще?

Затем поступило дополнение к задаче. Как оказалось, эти домены нужно проверять на присутствие вот на одном сайте, скажем yandex.ru:

Например вот так:

https://yandex.ru/sabai.tv

Куда вместо sabai.tv подставлять мои сграбленные доменчики.

С этим вроде тоже проблем быть не должно. Тем более, что при отсутствии домена в этом интернет-каталоге, он возвращает 404 ошибку.

Прийдется немного заддосить, напрячь этот сайтик.

Итак, поехали

Мне понадобятся две питоновские библиотеки:

requests - для создания HTTP GET запросов

beautifulsoup4 - для парсинга HTML и поиска полезной информации на странице.

Все это добро сложим в виртуальное окружение.

Создаю и активирую его.

mkdir finedomain
cd finedomain
virtualenv venv
source ./venv/bin/activate

Ставлю пакеты.

pip install requests beautifulsoup4

Пишу код с запросом в файле grabing.py.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# импортируем все что надо для работы
import requests
from bs4 import BeautifulSoup
import json
import time
import sys
# начало программы
print('Start')
# определяю строку с урлом
# к ней с конца буду прилеплять страницы
url = 'https://www.reg.ru/domain/deleted/?&free_from=12.06.2019&free_to=12.06.2019&order=ASC&sort_field=dname_idn%20%20%20%20&page='

# запрос первой страницы
r = requests.get(url+'0')
print(r.text)

Результат.

Неплохо, HTML получили, далее нужно распарсить это все добро beautifulsoup-ом.

soup = BeautifulSoup(r.text, 'html.parser')

Теперь, в переменной soup у нас не только весь код страницы, но и инструменты для поиска ее элементов.

Открываем инспектор браузера и смотрим где у нас список.

Ага, таблица с классом b-table__content. Нет ничего проще ее вытянуть так.

table = soup.find("table",{"class": "b-table__content"})

find() - ищет один элемент findAll() - найдет список

Далее получу tr-ки (строки) из тега tbody.

tbody = table.find("tbody")
trs = tbody.findAll("tr")

Побегу по ним циклом, найду td-шки (ячейки таблицы) и выведу из первой по счету доменное имя.

soup = BeautifulSoup(r.text, 'html.parser')
table = soup.find("table",{"class": "b-table__content"})
tbody = table.find("tbody")
trs = tbody.findAll("tr")
for tr in trs:
   tds = tr.findAll("td")
   print(tds[0].text)

Сработало!

Теперь создаем список для хранения доменов и даты истечения, и в цикле заполню его.

Полный код получился таким.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# импортируем все что надо для работы
import requests
from bs4 import BeautifulSoup
import json
import time
# начало программы
print('Start')
# определяю строку с урлом
# к ней с конца буду прилеплять страницы
url = 'https://www.reg.ru/domain/deleted/?&free_from=12.06.2019&free_to=12.06.2019&order=ASC&sort_field=dname_idn%20%20%20%20&page='

# запрос первой страницы
r = requests.get(url+'0')

# тут буду хранить домены
data = []

# парсим html
soup = BeautifulSoup(r.text, 'html.parser')

# находим первую таблицу по тегу и css классу
table = soup.find("table",{"class": "b-table__content"})

# в ней блок tbody по имени тега
tbody = table.find("tbody")

# строки
trs = tbody.findAll("tr")
for tr in trs:
   # ячейки
   tds = tr.findAll("td")
   # добавляем домен и срок истечения в список
   data.append({"domain": tds[0].text, "date_expire": tds[2].text})

print(data)

Время проверить эти домены на сайте.

Сделаю для этого функцию, принимающую доменное имя параметром.

def check_domain(domain):
   # формирую url, адрес подставляя домен в строку
   url = 'https://yandex.ru/%s' % domain
   # пробую сделать запрос
   try:
       # получаю страницу
       r = requests.get(url)
       if r.status_code == 404: # проверяю статус
           print('Domain %s result %s' % (domain, 'FAIL!'))
           return False
       else:
           print('Domain %s result %s' % (domain, 'SUCCESS'))
           # если повезло и домен нашли
           return True
   # это если запрос обрушился по какой то причине        
   except:
       print('Request error %s' % url)
       return False

Осталось вызвать эту функцию в цикле.

for tr in trs:
   # ячейки
   tds = tr.findAll("td")
   # добавляем домен и срок истечения в список
   data.append({"domain": tds[0].text, "date_expire": tds[2].text})
   # проверяю домен
   check_domain(tds[0].text)

Результат не утешает и попаданий на первой странице нет, зато работает!

Теперь мне нужно определить конец постраничной “нафигации” и прогнать процесс по всем доменам на указанную дату.

В лучших традициях функционального программирования делаю функцию.

def check_end(soup):
''' Определяю конец постранички '''
   try:
       # на конечной странице был замечен заголовок h1 с текстом
       '''
               Доменов, отвечающих заданным критериям фильтрации, не найдено.
       '''
       h2 = soup.find("h2")
       # тут для поиска сказало что нужно вначале кодировать в UTF-8
       if h2.text.encode('utf-8').find('отвечающих заданным критериям')>0:
           return True
       else:
           return False
   except:
       return False

Мучу цикл while пока не дошло до конца со счетчиком страниц.

is_end = False
page = 0
while not is_end:
   # определяю строку с урлом
   # к ней с конца буду прилеплять страницы
   url = 'https://www.reg.ru/domain/deleted/?&free_from=12.06.2019&free_to=12.06.2019&order=ASC&sort_field=dname_idn%20%20%20%20&page=%s' % page
   print("Делаю страницу %s" % page)
   # добавляем счетчик страниц
   page = page + 1

   # запрос первой страницы
   r = requests.get(url)

   # тут буду хранить домены
   data = []

   # парсим html
   soup = BeautifulSoup(r.text, 'html.parser')

   # проверим конец постранички
   if check_end(soup):
       is_end = True
       break # ломаем цикл


   # находим первую таблицу по тегу и css классу
   table = soup.find("table",{"class": "b-table__content"})

   # в ней блок tbody по имени тега
   tbody = table.find("tbody")

   # строки
   trs = tbody.findAll("tr")
   for tr in trs:
       # ячейки
       tds = tr.findAll("td")
       # добавляем домен и срок истечения в список
       data.append({"domain": tds[0].text, "date_expire": tds[2].text})
       # проверяю домен
       check_domain(tds[0].text)

Решил прервать процесс по ctrl+c, получил такой облом.

Пришлось тушить терминал, обидное недоразумение.

Случилось оно в этом блоке при проверке домена:

except:
   print('Request error %s' % url)
   return False

А если я отработаю исключение KeyboardInterrupt?

try:
   # получаю страницу
   ...
except KeyboardInterrupt: # выход по ctrl+c
   print("Ну пока!")
   sys.exit() # нагло вываливаемся из проги
# это если запрос обрушился по какой то другой причине        
except:
   print('Request error %s' % url)
   return False

Намного лучше!

Осталось забрать дату у пользователя где то в начале скрипта.

print("Вводи дату типа 12.06.2019:     ")
user_date = raw_input() #
print("Работаем по {}".format(user_date))

Просто input() не канает! Пользуйтесь только raw_input.

И вставить ее в урл запроса.

В конце я выгружу успешные домены в файлик.

def save_success(domain):
   with open('success.txt', 'a+') as of: # открываем для добавления и создаем если нет
       of.write(domain+';')
       print('Domain %s result %s' % (domain, 'SUCCESS'))

Полный код программы.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# импортируем все что надо для работы
import requests
from bs4 import BeautifulSoup
import json
import time
import sys
# начало программы
print('Начинаем грабить домены.')
print("Вводи за какую дату? (типа 12.06.2019):   ")
user_date = raw_input()
print("Работаем по {}".format(user_date))
def save_success(domain):
   with open('success.txt', 'a+') as of: # открываем для добавления и создаем если нет
       of.write(domain+';')
       print('Domain %s result %s' % (domain, 'SUCCESS'))

def check_domain(domain):
   # формирую url, адрес подставляя домен в строку
   url = 'https://yandex.ru/%s' % domain
   # пробую сделать запрос
   try:
       # получаю страницу
       r = requests.get(url)
       if r.status_code == 404: # проверяю статус
           print('Domain %s result %s' % (domain, 'FAIL!'))
           return False
       else:
           print('Domain %s result %s' % (domain, 'SUCCESS'))
           # если повезло и домен нашли
           return True
   except KeyboardInterrupt: # выход по ctrl+c
       print("Ну пока!")
       sys.exit() # нагло вываливаемся из проги
   # это если запрос обрушился по какой то причине        
   except:
       print('Request error %s' % url)
       return False

def check_end(soup):
   ''' Определяю конец постранички '''
   try:
       # на конечной странице был замечен заголовок h1 с текстом
       '''
               Доменов, отвечающих заданным критериям фильтрации, не найдено.
       '''
       h2 = soup.find("h2")
       # тут для поиска сказало что нужно вначале кодировать в UTF-8
       if h2.text.encode('utf-8').find('отвечающих заданным критериям')>0:
           return True
       else:
           return False
   except:
       return False

is_end = False
page = 0
while not is_end:
   # определяю строку с урлом
   # к ней с конца буду прилеплять страницы
   url = 'https://www.reg.ru/domain/deleted/?&free_from=%s&free_to=%s&order=ASC&sort_field=dname_idn%20%20%20%20&page=%s' % (user_date,user_date,page)
   print("Делаю страницу %s" % page)
   # добавляем счетчик страниц
   page = page + 1

   # запрос первой страницы
   r = requests.get(url)

   # тут буду хранить домены
   data = []

   # парсим html
   soup = BeautifulSoup(r.text, 'html.parser')

   # проверим конец постранички
   if check_end(soup):
       is_end = True
       break # ломаем цикл


   # находим первую таблицу по тегу и css классу
   table = soup.find("table",{"class": "b-table__content"})

   # в ней блок tbody по имени тега
   tbody = table.find("tbody")

   # строки
   trs = tbody.findAll("tr")
   for tr in trs:
       # ячейки
       tds = tr.findAll("td")
       # добавляем домен и срок истечения в список
       data.append({"domain": tds[0].text, "date_expire": tds[2].text})
       # проверяю домен
       if check_domain(tds[0].text):
           save_success(tds[0].text)

print('The end')

Выводы

В статье освещены приемы программирования на языке Python на примере реальной, практической задачи. Изложены основные функции Python библиотек requests и BeautifulSoup для получения содержимого страницы , поиска и извлечения из нее полезной информации с сохранением в текстовый файл.

5/5
Проголосовало людей: 1
СОДЕРЖАНИЕ
СТАТЬИ
Итак, поехали
Выводы
Домены с истекающим сроком
Дмитрий Жариков
Дмитрий Жариков
Пишем сигнальный сервер Tornado
Итак, это третья и последняя статья нашего цикла, где речь. В предыдущих двух мы рассматривали…
Дмитрий Жариков
Дмитрий Жариков
Кейс: Оптовые поставки товаров
Как мы сделали ребрендинг сайта известной компании TopChinaOpt, которая занимается оптовыми поставками и заказами продукции…
Полина Приходько
Полина Приходько
ПОЛУЧАТЬ ИНТЕРЕСНЫЕ СТАТЬИ
Уже подписались 236 человек
Автор
185
0
Дмитрий Жариков
Дмитрий
Жариков
Возможно
Мы уже неоднократно рассматривали причины санкций Google в предыдущих материалах. Так известно, что поисковую систему…
Екатерина Шведа
Екатерина Шведа
Продвижение сайтов за рубежом. На что обратить внимание Если Вы планируете продвинуть свой сайт на…
Wezom
Wezom
Что делать программисту, если он «подсел» на JavaScript? Для начала — прочесть эту статью!
Галина Назарова
Галина Назарова
Давайте начнем
беседу!
КОММЕНТАРИИ0
ОСТАВИТЬ КОММЕНТАРИЙ К СТАТЬЕ
ПОДПИСЫВАЙТЕСЬ НА РАССЫЛКУ АЙТЫЖБЛОГ
ХОТИТЕ ПОЛУЧАТЬ 
ИНТЕРЕСНЫЕ СТАТЬИ?
Уже подписались 236 человек
313
ПОПИСЧИКОВ
ЧИТАТЬ
4295
ПОПИСЧИКОВ
СЛЕДИТЬ
9307
ПОПИСЧИКОВ
СЛЕДИТЬ