Что может заблокировать parsing HTML-страницы?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Факторы, которые могут заблокировать парсинг HTML
Парсинг HTML — это не просто загрузка и разбор текста. Есть много причин, по которым процесс может замедлиться, зависнуть или вообще сломаться. Расскажу про наиболее частые проблемы.
1. Сетевые проблемы (Most Common)
Медленное подключение или таймауты:
const axios = require('axios');
const cheerio = require('cheerio');
async function parseHTML(url) {
try {
const response = await axios.get(url, {
timeout: 5000,
});
const $ = cheerio.load(response.data);
return $('body').text();
} catch (error) {
if (error.code === 'ECONNABORTED') {
console.error('Таймаут: сервер не ответил');
}
}
}
DNS резолюция: если DNS медленно работает, запрос может зависнуть. Решение — использовать публичные DNS (8.8.8.8) или увеличить таймаут.
2. Очень большой HTML (Blocking)
Если страница весит 100+ МБ, загрузка её в память может заблокировать весь процесс:
const fs = require('fs');
const { pipeline } = require('stream');
axios.get(url, { responseType: 'stream' })
.then(response => {
return new Promise((resolve, reject) => {
pipeline(
response.data,
fs.createWriteStream('page.html'),
(err) => {
if (err) reject(err);
else resolve();
}
);
});
});
3. JavaScript на странице (Critical!)
Современные страницы генерируют контент через JavaScript. Парсер, который просто загружает HTML, получит пустую страницу:
const puppeteer = require('puppeteer');
async function parseWithJS(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
await page.waitForSelector('.content');
const content = await page.$eval('.content', el => el.textContent);
await browser.close();
return content;
}
Puppeteer открывает полноценный браузер, поэтому заблокирует потребление памяти и CPU. Нужна оптимизация если много параллельных запросов.
4. Неправильная кодировка символов
Если страница в кодировке, которую мы не указали, парсинг будет неправильным:
const iconv = require('iconv-lite');
const response = await axios.get(url, { responseType: 'arraybuffer' });
const html = iconv.decode(response.data, 'windows-1251');
const $ = cheerio.load(html);
5. Защита от парсинга (Anti-Scraping)
Сайт может блокировать парсеры через User-Agent проверку:
const response = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
IP блокировка: если делаю слишком много запросов, мой IP забанят. Решение — использовать прокси или delay:
async function parseWithDelay(urls) {
for (const url of urls) {
const response = await axios.get(url);
await new Promise(r => setTimeout(r, 1000));
}
}
6. Синтаксические ошибки в HTML
Если HTML некорректный, парсер может глючить. Cheerio обычно справляется автоматически, но лучше валидировать.
7. Неэффективные селекторы
Если выбираю элементы неправильно, операция может быть медленной:
const links = $('a');
links.each((i, el) => {
// работаем с уже выбранными элементами
});
8. Recursive parsing без лимита
Если страница имеет глубокую вложенность:
function parseRecursive(element, depth = 0) {
if (depth > 100) return;
}
Пример надежного парсера
async function robustParse(url) {
const maxRetries = 3;
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
const response = await axios.get(url, { timeout: 10000 });
const $ = cheerio.load(response.data);
return { success: true, data: $('body').text() };
} catch (error) {
lastError = error;
await new Promise(r => setTimeout(r, 1000 * (i + 1)));
}
}
return { success: false, error: lastError.message };
}
Лучшие практики
- Всегда используй таймауты (5-30 сек)
- Streaming для больших файлов
- Для JS-контента используй Puppeteer/Playwright с лимитом параллельных экземпляров
- Кэширование результатов
- Обработка ошибок и retry логика с exponential backoff
- Мониторинг — сколько времени занимает, какие ошибки