new commit
This commit is contained in:
419
public/test-parser.html
Normal file
419
public/test-parser.html
Normal file
@ -0,0 +1,419 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Тест Парсера Wildberries - ОБНОВЛЕНО</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
color: #2d3748;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
background: #48bb78;
|
||||
color: white;
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.update-info {
|
||||
background: #e6fffa;
|
||||
border: 2px solid #48bb78;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.update-info h3 {
|
||||
color: #2d3748;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.update-info ul {
|
||||
color: #4a5568;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
background: #f7fafc;
|
||||
border-radius: 8px;
|
||||
padding: 25px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.preset-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.preset-btn {
|
||||
background: #667eea;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.preset-btn:hover {
|
||||
background: #5a67d8;
|
||||
}
|
||||
|
||||
.test-btn {
|
||||
background: #48bb78;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 15px 30px;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.test-btn:hover:not(:disabled) {
|
||||
background: #38a169;
|
||||
}
|
||||
|
||||
.test-btn:disabled {
|
||||
background: #a0aec0;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: none;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.loading.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 3px solid #e2e8f0;
|
||||
border-radius: 50%;
|
||||
border-top-color: #667eea;
|
||||
animation: spin 1s ease-in-out infinite;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.results {
|
||||
display: none;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.results.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.result-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
font-size: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background: white;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.product-details h3 {
|
||||
margin: 0 0 10px 0;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.positions-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.positions-table th,
|
||||
.positions-table td {
|
||||
padding: 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.positions-table th {
|
||||
background: #4a5568;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.position-found {
|
||||
color: #48bb78;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.position-not-found {
|
||||
color: #f56565;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.error {
|
||||
background: #fed7d7;
|
||||
border: 2px solid #f56565;
|
||||
color: #c53030;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🎯 Тест Парсера Wildberries</h1>
|
||||
<span class="status-badge">✅ РАБОТАЕТ</span>
|
||||
</div>
|
||||
|
||||
<div class="update-info">
|
||||
<h3>🚀 Парсер обновлен и работает!</h3>
|
||||
<ul>
|
||||
<li><strong>Решена проблема блокировки:</strong> Добавлены продвинутые методы обхода защиты Wildberries</li>
|
||||
<li><strong>Улучшенная маскировка:</strong> Парсер теперь имитирует реальное поведение пользователя</li>
|
||||
<li><strong>API поиск:</strong> Добавлен резервный поиск через внутренние API</li>
|
||||
<li><strong>Стабильная работа:</strong> Тестирование показало успешное нахождение товаров</li>
|
||||
<li><strong>Корректная обработка:</strong> Правильно обрабатывает случаи "товар не найден"</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>🧪 Протестировать парсер</h2>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="query">Поисковый запрос:</label>
|
||||
<input type="text" id="query" value="лабубу" placeholder="Введите поисковый запрос">
|
||||
<div class="preset-buttons">
|
||||
<button class="preset-btn" onclick="setPreset('лабубу', '447020075')">Лабубу (работает)</button>
|
||||
<button class="preset-btn" onclick="setPreset('плюшевая игрушка', '197761909')">Плюшевая игрушка (работает)</button>
|
||||
<button class="preset-btn" onclick="setPreset('игрушка', '123456789')">Тест "не найдено"</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="article">Артикул товара:</label>
|
||||
<input type="text" id="article" value="447020075" placeholder="Введите артикул">
|
||||
</div>
|
||||
|
||||
<button class="test-btn" onclick="testParser()" id="testBtn">
|
||||
🔍 Запустить тест парсера
|
||||
</button>
|
||||
|
||||
<div class="loading" id="loading">
|
||||
<div class="spinner"></div>
|
||||
Парсинг в процессе... Это может занять до 1 минуты
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="results" id="results">
|
||||
<div class="result-header">
|
||||
<span class="status-icon" id="statusIcon"></span>
|
||||
<h2 id="resultTitle"></h2>
|
||||
</div>
|
||||
|
||||
<div id="resultContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function setPreset(query, article) {
|
||||
document.getElementById('query').value = query;
|
||||
document.getElementById('article').value = article;
|
||||
}
|
||||
|
||||
async function testParser() {
|
||||
const query = document.getElementById('query').value.trim();
|
||||
const article = document.getElementById('article').value.trim();
|
||||
|
||||
if (!query || !article) {
|
||||
alert('Пожалуйста, заполните все поля');
|
||||
return;
|
||||
}
|
||||
|
||||
const testBtn = document.getElementById('testBtn');
|
||||
const loading = document.getElementById('loading');
|
||||
const results = document.getElementById('results');
|
||||
|
||||
// Показываем индикатор загрузки
|
||||
testBtn.disabled = true;
|
||||
loading.classList.add('active');
|
||||
results.classList.remove('active');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/test-parser', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: query,
|
||||
myArticleId: article
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
showResults(true, data.data, data.message);
|
||||
} else {
|
||||
showResults(false, null, data.error || 'Произошла ошибка');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
showResults(false, null, 'Ошибка соединения: ' + error.message);
|
||||
} finally {
|
||||
testBtn.disabled = false;
|
||||
loading.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
function showResults(success, data, message) {
|
||||
const results = document.getElementById('results');
|
||||
const statusIcon = document.getElementById('statusIcon');
|
||||
const resultTitle = document.getElementById('resultTitle');
|
||||
const resultContent = document.getElementById('resultContent');
|
||||
|
||||
if (success && data) {
|
||||
statusIcon.textContent = '✅';
|
||||
resultTitle.textContent = 'Парсинг выполнен успешно!';
|
||||
|
||||
const product = data.product;
|
||||
const positions = data.positions;
|
||||
|
||||
const foundPositions = positions.filter(p => p.position !== null);
|
||||
const isFound = foundPositions.length > 0;
|
||||
|
||||
resultContent.innerHTML = `
|
||||
<div class="product-card">
|
||||
<div class="product-info">
|
||||
<img src="${product.imageUrl}" alt="${product.name}" class="product-image" onerror="this.src='/images/no-image.svg'">
|
||||
<div class="product-details">
|
||||
<h3>${product.name}</h3>
|
||||
<p><strong>Бренд:</strong> ${product.brand}</p>
|
||||
<p><strong>Цена:</strong> ${product.price} ₽</p>
|
||||
<p><strong>Артикул:</strong> ${product.article}</p>
|
||||
<p><strong>Статус:</strong> ${isFound ? '<span class="position-found">Найден в поиске</span>' : '<span class="position-not-found">Не найден в поиске</span>'}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Позиции по городам:</h3>
|
||||
<table class="positions-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Город</th>
|
||||
<th>Код</th>
|
||||
<th>Позиция</th>
|
||||
<th>Статус</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${positions.map(pos => `
|
||||
<tr>
|
||||
<td>${pos.city}</td>
|
||||
<td>${pos.cityCode}</td>
|
||||
<td>${pos.position || '—'}</td>
|
||||
<td>${pos.position ? '<span class="position-found">Найден</span>' : '<span class="position-not-found">Не найден</span>'}</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p style="margin-top: 20px; color: #4a5568; font-style: italic;">${message}</p>
|
||||
`;
|
||||
} else {
|
||||
statusIcon.textContent = '❌';
|
||||
resultTitle.textContent = 'Ошибка парсинга';
|
||||
resultContent.innerHTML = `<div class="error">${message}</div>`;
|
||||
}
|
||||
|
||||
results.classList.add('active');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user