Новые правки
This commit is contained in:
parent
79db7c8563
commit
a5f208a132
19 changed files with 852 additions and 1 deletions
158
frontend/scripts/analyze-posts.ts
Normal file
158
frontend/scripts/analyze-posts.ts
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import PocketBase from 'pocketbase';
|
||||
|
||||
const PB_URL = 'http://127.0.0.1:8090';
|
||||
const pb = new PocketBase(PB_URL);
|
||||
|
||||
interface Post {
|
||||
id: string;
|
||||
title: string;
|
||||
content: string;
|
||||
slug: string;
|
||||
category: string;
|
||||
draft: boolean;
|
||||
}
|
||||
|
||||
interface AnalysisResult {
|
||||
title: string;
|
||||
slug: string;
|
||||
category: string;
|
||||
hasClaim: boolean;
|
||||
hasTakeaway: boolean;
|
||||
hasPronouns: boolean;
|
||||
hasProof: boolean;
|
||||
h2Issues: string[];
|
||||
problems: string[];
|
||||
}
|
||||
|
||||
function analyzePost(post: Post): AnalysisResult {
|
||||
const result: AnalysisResult = {
|
||||
title: post.title,
|
||||
slug: post.slug,
|
||||
category: post.category || 'unknown',
|
||||
hasClaim: false,
|
||||
hasTakeaway: false,
|
||||
hasPronouns: false,
|
||||
hasProof: false,
|
||||
h2Issues: [],
|
||||
problems: []
|
||||
};
|
||||
|
||||
const content = post.content || '';
|
||||
|
||||
// Check for Claim patterns directly in content (including HTML)
|
||||
// Look for new first paragraph that starts with Claim-like content
|
||||
// Check first 1500 chars to catch posts where Claim may have been inserted
|
||||
const claimPatterns = [
|
||||
{ pattern: /За\s+\d+/i, name: 'За год' },
|
||||
{ pattern: /В\s+\d+\s+(год|месяц)/i, name: 'В год/месяц' },
|
||||
{ pattern: /\d+%/i, name: 'Процент' },
|
||||
{ pattern: /Вы можете/i, name: 'Вы можете' },
|
||||
];
|
||||
|
||||
const prefix = content.substring(0, 3000);
|
||||
result.hasClaim = claimPatterns.some(p => p.pattern.test(prefix));
|
||||
|
||||
// Proof: contains numbers
|
||||
const numberPatterns = [/\d+%/g, /\d+\s+(лет|месяцев|дней|тысяч|рублей)/gi];
|
||||
result.hasProof = numberPatterns.some(p => p.test(content));
|
||||
|
||||
// Pronouns check
|
||||
const pronouns = /\b(мы|наш|наша|наши|их|он|она|оно|этот|эта|эти)\b/gi;
|
||||
result.hasPronouns = pronouns.test(content);
|
||||
|
||||
// Takeaway check
|
||||
const takeawayPatterns = [
|
||||
/что\s+делать/i,
|
||||
/обращайтесь/i,
|
||||
/позвоните/i,
|
||||
/закажите/i,
|
||||
/получите/i,
|
||||
/напишите/i,
|
||||
/свяжитесь/i
|
||||
];
|
||||
result.hasTakeaway = takeawayPatterns.some(p => p.test(content));
|
||||
|
||||
// H2 analysis - check all H2s in content
|
||||
const h2Matches = content.match(/<h2[^>]*>[^<]+<\/h2>/gi) || [];
|
||||
const badH2s = ['проблема', 'подход', 'ситуация', 'что было', 'решение', 'как помочь', 'поможет'];
|
||||
h2Matches.forEach(h2 => {
|
||||
const h2Text = h2.toLowerCase();
|
||||
if (badH2s.some(b => h2Text.includes(b))) {
|
||||
result.h2Issues.push(h2.replace(/<[^>]+>/g, ''));
|
||||
}
|
||||
});
|
||||
|
||||
// Collect problems
|
||||
if (!result.hasClaim) result.problems.push('Нет Claim в первом абзаце');
|
||||
if (!result.hasTakeaway) result.problems.push('Нет Takeaway');
|
||||
if (result.hasPronouns) result.problems.push('Есть местоимения');
|
||||
if (!result.hasProof) result.problems.push('Нет конкретных цифр');
|
||||
if (result.h2Issues.length > 0) result.problems.push(`Размытые H2: ${result.h2Issues.join(', ')}`);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('📊 Анализ постов блога по методологии Answer Unit\n');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
try {
|
||||
const postsResult = await pb.collection('posts').getList(1, 500);
|
||||
const posts = postsResult.items as unknown as Post[];
|
||||
|
||||
console.log(`Найдено постов: ${posts.length}\n`);
|
||||
|
||||
// Filter for non-draft posts
|
||||
const activePosts = posts.filter(p => !p.draft);
|
||||
console.log(`Опубликованных постов: ${activePosts.length}\n`);
|
||||
|
||||
const results = activePosts.map(analyzePost);
|
||||
|
||||
// Stats
|
||||
const withClaim = results.filter(r => r.hasClaim).length;
|
||||
const withTakeaway = results.filter(r => r.hasTakeaway).length;
|
||||
const withPronouns = results.filter(r => r.hasPronouns).length;
|
||||
const withProof = results.filter(r => r.hasProof).length;
|
||||
const withH2Issues = results.filter(r => r.h2Issues.length > 0).length;
|
||||
const problemCount = results.filter(r => r.problems.length > 0).length;
|
||||
|
||||
const n = activePosts.length;
|
||||
console.log('📈 ОБЩАЯ СТАТИСТИКА:');
|
||||
console.log('-'.repeat(40));
|
||||
console.log(` ✓ Есть Claim: ${withClaim}/${n} (${n > 0 ? Math.round(withClaim/n*100) : 0}%)`);
|
||||
console.log(` ✓ Есть Takeaway: ${withTakeaway}/${n} (${n > 0 ? Math.round(withTakeaway/n*100) : 0}%)`);
|
||||
console.log(` ✗ Есть местоимения: ${withPronouns}/${n} (${n > 0 ? Math.round(withPronouns/n*100) : 0}%)`);
|
||||
console.log(` ✓ Есть Proof (цифры): ${withProof}/${n} (${n > 0 ? Math.round(withProof/n*100) : 0}%)`);
|
||||
console.log(` ✗ Проблемы с H2: ${withH2Issues}/${n}`);
|
||||
console.log(` ⚠️ Постов с проблемами: ${problemCount}/${n}\n`);
|
||||
|
||||
// Problem posts
|
||||
const problemPosts = results.filter(r => r.problems.length > 0);
|
||||
|
||||
if (problemPosts.length > 0) {
|
||||
console.log('❌ ПОСТЫ С ПРОБЛЕМАМИ:');
|
||||
console.log('-'.repeat(40));
|
||||
problemPosts.forEach((r, i) => {
|
||||
console.log(`\n${i+1}. ${r.title}`);
|
||||
console.log(` slug: ${r.slug}`);
|
||||
console.log(` category: ${r.category}`);
|
||||
r.problems.forEach(p => console.log(` - ${p}`));
|
||||
});
|
||||
}
|
||||
|
||||
// Good posts
|
||||
const goodPosts = results.filter(r => r.problems.length === 0);
|
||||
if (goodPosts.length > 0) {
|
||||
console.log('\n\n✅ ПОСТЫ БЕЗ ПРОБЛЕМ:');
|
||||
console.log('-'.repeat(40));
|
||||
goodPosts.forEach(r => {
|
||||
console.log(` • ${r.title}`);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Ошибка:', error);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue