Что вы получите:
Каждый опубликованный гостевой пост — это потенциальный линк‑вход в ваш «жирный» траст. Если в этом посте скрыты спам‑комментарии или ссылки‑платформы, поисковые системы воспринимают страницу как «низкокачественную», а ваш траст падает.
Аналогия: представьте, что ваш сайт — это ресторан. Гостевой пост — это блюдо, а спам‑комментарий — это крошка на столе. Если крошек слишком много, клиенту будет неприятно, и он уйдёт к конкуренту.
| Термин | Пиньинь | Иероглифы | Что означает |
|---|---|---|---|
| спам‑комментарий | laji pinglun | 垃圾评论 | Непрошенный, рекламный или вредоносный комментарий |
| гостевой пост | guest post | — | Статья, размещённая на чужом ресурсе с обратной ссылкой |
| донор | donor | — | Сайт‑партнёр, на котором вы размещаете ссылки |
| API | API | — | Интерфейс программного взаимодействия |
| регулярное выражение | regular expression | — | Шаблон для поиска текста |
Все ключевые термины выделены жирным шрифтом, чтобы вы могли быстро находить их в тексте.
+-------------------+ +-------------------+ +-------------------+
| Сбор данных | ---> | Фильтрация | ---> | Удаление/Модерация|
| (API, парсинг) | | (regex, ML) | | (API, запросы) |
+-------------------+ +-------------------+ +-------------------+
| | |
v v v
JSON‑файл/DB Список «плохих» ID Лог‑файл/отчёт
| Шаг | Команда | Описание |
|---|---|---|
| 1 | python -V |
Убедитесь, что установлен Python 3.8+ |
| 2 | pip install requests beautifulsoup4 pandas sklearn |
Установите необходимые библиотеки |
| 3 | git clone https://github.com/yourrepo/donor-cleaner.git |
Скачайте шаблон проекта (ссылка rel="nofollow") |
| 4 | cp config.example.json config.json |
Скопируйте конфиг и укажите api_key, donor_url |
Совет: храните
api_keyв переменной окружения (export DONOR_API_KEY=…) – так вы не случайно не опубликуете его в репозитории.
import requests, json
API_URL = "https://donor.example.com/api/v1/posts"
HEADERS = {"Authorization": f"Bearer {os.getenv('DONOR_API_KEY')}"}
def fetch_posts(page=1):
resp = requests.get(API_URL, headers=HEADERS, params={"page": page})
resp.raise_for_status()
return resp.json() # { "items": [...], "total_pages": N }
all_posts = []
for p in range(1, fetch_posts()["total_pages"] + 1):
all_posts.extend(fetch_posts(p)["items"])
print(f"Получено {len(all_posts)} постов")
Что делает код:
Если у вашего донора нет API, используйте BeautifulSoup для парсинга HTML‑страницы со списком постов.
| Пример | Описание |
|---|---|
r"https?://\S+\.ru" |
Ссылки на русскоязычные сайты (часто используют спаммеры) |
r"\b(?:купить|дешево|скидка)\b" |
Ключевые слова рекламных комментариев |
r"[^\w\s,.!?-]" |
Наличие большого количества спецсимволов (мусор) |
import re
spam_patterns = [
re.compile(r"https?://\S+\.ru", re.I),
re.compile(r"\b(?:купить|дешево|скидка)\b", re.I),
re.compile(r"[^\w\s,.!?-]"),
]
def is_spam(text):
return any(p.search(text) for p in spam_patterns)
spam_comments = [c for c in all_comments if is_spam(c["body"])]
print(f"Найдено {len(spam_comments)} спам‑комментариев")
Если у вас большой объём данных, обучите простую Logistic Regression на признаках: длина текста, количество ссылок, наличие ключевых слов.
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
vectorizer = TfidfVectorizer(max_features=5000, ngram_range=(1,2))
X = vectorizer.fit_transform([c["body"] for c in all_comments])
y = [1 if c["is_spam"] else 0 for c in all_comments] # разметка вручную
model = LogisticRegression()
model.fit(X, y)
def ml_is_spam(text):
return model.predict(vectorizer.transform([text]))[0] == 1
Сочетание regex и ML даёт максимальную точность и минимальные ложные срабатывания.
DELETE_URL = "https://donor.example.com/api/v1/comments/{id}"
def delete_comment(comment_id):
resp = requests.delete(DELETE_URL.format(id=comment_id), headers=HEADERS)
resp.raise_for_status()
return resp.status_code == 204
log = []
for c in spam_comments:
try:
if delete_comment(c["id"]):
log.append({"id": c["id"], "status": "deleted"})
except Exception as e:
log.append({"id": c["id"], "status": f"error: {e}"})
with open("clean_log.json", "w", encoding="utf-8") as f:
json.dump(log, f, ensure_ascii=False, indent=2)
print("Очистка завершена, см. clean_log.json")
Что важно:
Чтобы чистка происходила регулярно, добавьте задачу в cron (Linux) или Task Scheduler (Windows).
0 3 * * * /usr/bin/python3 /home/user/donor-cleaner/clean.py >> /var/log/donor_clean.log 2>&1
Эта строка будет запускать скрипт каждый день в 03:00 утра, когда нагрузка на сервер минимальна.
| Мероприятие | Как реализовать |
|---|---|
| CAPTCHA на форму комментариев | Включить в настройках CMS (обычно в разделе «Безопасность») |
| Черный список IP | Добавить в .htaccess правила Deny from <IP> |
| Модерация новых комментариев | Установить в CMS статус «pending» и проверять через API каждую новую запись |
| Тайм‑ауит | Ограничить количество комментариев от одного пользователя за час (например, 3) |
Эти меры снижают нагрузку на скрипт и экономят ресурсы.
delete_comment выводите print и проверяйте, какие записи будут удалены. error и уточняйте причину (недостаток прав, тайм‑ауты). dry_run_delete, которая выводит ID комментариев, которые будут удалены, но не делает запросов к API. Запустите её на небольшом наборе данных и проверьте, совпадают ли результаты с вашими ожиданиями. crontab -e). Укажите, чтобы скрипт запускался каждый час и записывал вывод в отдельный лог‑файл. Проверьте, что запись действительно появляется. 403 Forbidden? Составьте чек‑лист из минимум трёх пунктов. Итоги: вы теперь знаете, как собрать все посты и комментарии с донорского сайта, отфильтровать спам с помощью регулярных выражений и машинного обучения, автоматически удалить «мусор» и настроить регулярный запуск скрипта. Применяйте полученные навыки, и ваш «жирный» траст будет расти без лишних штрафов поисковых систем. Удачной чистки!