Интеграция Firecrawl с WordPress для автоматического наполнения контентом и мониторинга
firecrawl-integration/
├── firecrawl-integration.php
├── includes/
│ ├── class-firecrawl-api.php
│ ├── class-content-importer.php
│ ├── class-admin-page.php
│ └── class-scheduler.php
├── admin/
│ ├── css/
│ ├── js/
│ └── partials/
└── public/
├── css/
└── js/
<?php
/**
* Plugin Name: Firecrawl Integration
* Description: Автоматический импорт контента через Firecrawl API
* Version: 1.0.0
* Author: Your Name
*/
// Предотвращаем прямой доступ
if (!defined('ABSPATH')) {
exit;
}
// Основной класс плагина
class FirecrawlIntegration {
private $api_key;
private $api_url = 'https://api.firecrawl.ru/v1';
public function __construct() {
add_action('init', array($this, 'init'));
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('wp_ajax_firecrawl_import', array($this, 'ajax_import_content'));
// Планировщик задач
add_action('firecrawl_scheduled_import', array($this, 'scheduled_import'));
if (!wp_next_scheduled('firecrawl_scheduled_import')) {
wp_schedule_event(time(), 'hourly', 'firecrawl_scheduled_import');
}
}
public function init() {
$this->api_key = get_option('firecrawl_api_key');
}
// Добавляем страницу в админку
public function add_admin_menu() {
add_management_page(
'Firecrawl Integration',
'Firecrawl',
'manage_options',
'firecrawl-integration',
array($this, 'admin_page')
);
}
// Страница настроек в админке
public function admin_page() {
?>
<div class="wrap">
<h1>Firecrawl Integration</h1>
<form method="post" action="options.php">
<?php
settings_fields('firecrawl_settings');
do_settings_sections('firecrawl_settings');
?>
<table class="form-table">
<tr>
<th scope="row">API Key</th>
<td>
<input type="text" name="firecrawl_api_key"
value="<?php echo esc_attr(get_option('firecrawl_api_key')); ?>"
class="regular-text" />
<p class="description">Введите ваш Firecrawl API ключ</p>
</td>
</tr>
<tr>
<th scope="row">Автоимпорт</th>
<td>
<label>
<input type="checkbox" name="firecrawl_auto_import"
value="1" <?php checked(1, get_option('firecrawl_auto_import'), true); ?> />
Включить автоматический импорт контента
</label>
</td>
</tr>
<tr>
<th scope="row">Поисковые запросы</th>
<td>
<textarea name="firecrawl_search_queries" rows="5" cols="50" class="large-text"><?php
echo esc_textarea(get_option('firecrawl_search_queries', 'новости технологий\nстартапы инвестиции\nИИ разработка'));
?></textarea>
<p class="description">Каждый запрос с новой строки</p>
</td>
</tr>
</table>
<?php submit_button(); ?>
</form>
<hr>
<h2>Ручной импорт</h2>
<div id="firecrawl-import-section">
<input type="text" id="firecrawl-url" placeholder="URL для парсинга" class="regular-text" />
<button id="firecrawl-import-btn" class="button button-primary">Импортировать</button>
<div id="firecrawl-import-result" style="margin-top: 20px;"></div>
</div>
<script>
jQuery(document).ready(function($) {
$('#firecrawl-import-btn').click(function() {
var url = $('#firecrawl-url').val();
if (!url) {
alert('Введите URL');
return;
}
$('#firecrawl-import-result').html('<p>Импортируем контент...</p>');
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'firecrawl_import',
url: url,
nonce: '<?php echo wp_create_nonce('firecrawl_import'); ?>'
},
success: function(response) {
if (response.success) {
$('#firecrawl-import-result').html('<p style="color: green;">Контент успешно импортирован! <a href="' + response.data.edit_link + '">Редактировать пост</a></p>');
} else {
$('#firecrawl-import-result').html('<p style="color: red;">Ошибка: ' + response.data + '</p>');
}
},
error: function() {
$('#firecrawl-import-result').html('<p style="color: red;">Произошла ошибка при импорте</p>');
}
});
});
});
</script>
</div>
<?php
}
// AJAX обработка импорта
public function ajax_import_content() {
// Проверка nonce для безопасности
if (!wp_verify_nonce($_POST['nonce'], 'firecrawl_import')) {
wp_die('Security check failed');
}
$url = sanitize_url($_POST['url']);
if (!$url) {
wp_send_json_error('Invalid URL');
return;
}
// Парсим контент через Firecrawl
$content_data = $this->scrape_content($url);
if ($content_data && $content_data['success']) {
// Создаем пост в WordPress
$post_id = $this->create_post_from_content($content_data['data'], $url);
if ($post_id) {
wp_send_json_success(array(
'post_id' => $post_id,
'edit_link' => admin_url('post.php?post=' . $post_id . '&action=edit')
));
} else {
wp_send_json_error('Failed to create post');
}
} else {
wp_send_json_error('Failed to scrape content');
}
}
// Парсинг контента через Firecrawl API
private function scrape_content($url) {
if (!$this->api_key) {
return false;
}
$response = wp_remote_post($this->api_url . '/scrape', array(
'headers' => array(
'X-API-Key' => $this->api_key,
'Content-Type' => 'application/json'
),
'body' => json_encode(array(
'url' => $url,
'formats' => array('markdown'),
'onlyMainContent' => true
)),
'timeout' => 30
));
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
return json_decode($body, true);
}
// Создание поста из контента
private function create_post_from_content($content_data, $source_url) {
$markdown = $content_data['markdown'] ?? '';
$metadata = $content_data['metadata'] ?? array();
// Конвертируем Markdown в HTML
$html_content = $this->markdown_to_html($markdown);
// Определяем заголовок
$title = $metadata['title'] ?? 'Imported Content from ' . parse_url($source_url, PHP_URL_HOST);
// Данные поста
$post_data = array(
'post_title' => sanitize_text_field($title),
'post_content' => wp_kses_post($html_content),
'post_status' => 'draft', // Сохраняем как черновик для проверки
'post_type' => 'post',
'post_category' => array(get_option('default_category')),
'meta_input' => array(
'firecrawl_source_url' => $source_url,
'firecrawl_import_date' => current_time('mysql'),
'firecrawl_original_title' => $metadata['title'] ?? '',
'firecrawl_description' => $metadata['description'] ?? ''
)
);
$post_id = wp_insert_post($post_data);
return $post_id;
}
// Простая конвертация Markdown в HTML
private function markdown_to_html($markdown) {
// Заголовки
$html = preg_replace('/^### (.*$)/m', '<h3>$1</h3>', $markdown);
$html = preg_replace('/^## (.*$)/m', '<h2>$1</h2>', $html);
$html = preg_replace('/^# (.*$)/m', '<h1>$1</h1>', $html);
// Ссылки
$html = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $html);
// Жирный текст
$html = preg_replace('/\*\*(.*?)\*\*/', '<strong>$1</strong>', $html);
// Курсив
$html = preg_replace('/\*(.*?)\*/', '<em>$1</em>', $html);
// Параграфы
$html = '<p>' . str_replace(array("\r\n", "\n", "\r"), '</p><p>', $html) . '</p>';
$html = str_replace('<p></p>', '', $html);
return $html;
}
// Автоматический импорт по расписанию
public function scheduled_import() {
if (!get_option('firecrawl_auto_import')) {
return;
}
$queries = get_option('firecrawl_search_queries', '');
if (empty($queries)) {
return;
}
$queries_array = explode("\n", $queries);
foreach ($queries_array as $query) {
$query = trim($query);
if (empty($query)) continue;
// Поиск контента через Firecrawl
$search_results = $this->search_content($query);
if ($search_results && $search_results['success']) {
$pages = $search_results['data']['pages'] ?? array();
// Импортируем первые 2 результата
foreach (array_slice($pages, 0, 2) as $page) {
// Проверяем, не импортировали ли мы уже этот URL
$existing = get_posts(array(
'meta_key' => 'firecrawl_source_url',
'meta_value' => $page['url'],
'post_type' => 'post',
'numberposts' => 1
));
if (empty($existing)) {
$content_data = $this->scrape_content($page['url']);
if ($content_data && $content_data['success']) {
$this->create_post_from_content($content_data['data'], $page['url']);
}
}
}
}
}
}
// Поиск контента через Firecrawl API
private function search_content($query) {
if (!$this->api_key) {
return false;
}
$response = wp_remote_post($this->api_url . '/search', array(
'headers' => array(
'X-API-Key' => $this->api_key,
'Content-Type' => 'application/json'
),
'body' => json_encode(array(
'query' => $query,
'limit' => 5,
'parseResults' => false
)),
'timeout' => 30
));
if (is_wp_error($response)) {
return false;
}
$body = wp_remote_retrieve_body($response);
return json_decode($body, true);
}
}
// Инициализируем плагин
new FirecrawlIntegration();
// Регистрируем настройки
add_action('admin_init', 'firecrawl_admin_init');
function firecrawl_admin_init() {
register_setting('firecrawl_settings', 'firecrawl_api_key');
register_setting('firecrawl_settings', 'firecrawl_auto_import');
register_setting('firecrawl_settings', 'firecrawl_search_queries');
}
// Очистка задач при деактивации
register_deactivation_hook(__FILE__, 'firecrawl_deactivation');
function firecrawl_deactivation() {
wp_clear_scheduled_hook('firecrawl_scheduled_import');
}
?>
<?php
// Дополнительный класс для WooCommerce
class FirecrawlWooCommerce {
public function __construct() {
add_action('admin_menu', array($this, 'add_woo_menu'));
add_action('wp_ajax_firecrawl_import_products', array($this, 'import_products'));
}
public function add_woo_menu() {
add_submenu_page(
'woocommerce',
'Firecrawl Products',
'Import Products',
'manage_woocommerce',
'firecrawl-products',
array($this, 'products_page')
);
}
public function import_products() {
$competitor_url = sanitize_url($_POST['competitor_url']);
// Парсим страницу каталога
$content = $this->scrape_catalog($competitor_url);
if ($content && $content['success']) {
$products = $this->extract_products($content['data']['markdown']);
foreach ($products as $product_data) {
$this->create_woo_product($product_data);
}
wp_send_json_success(array('imported' => count($products)));
} else {
wp_send_json_error('Failed to scrape catalog');
}
}
private function extract_products($markdown) {
// Простая логика извлечения товаров из markdown
$products = array();
// Ищем структуры типа:
// ## Название товара
// Цена: 1990 руб
// Описание...
$pattern = '/##\s*([^\n]+)\n.*?(?:цена|price):\s*([0-9,.\s]+).*?\n(.*?)(?=##|$)/is';
preg_match_all($pattern, $markdown, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$products[] = array(
'name' => trim($match[1]),
'price' => $this->extract_price($match[2]),
'description' => trim($match[3])
);
}
return $products;
}
private function extract_price($price_text) {
preg_match('/([0-9,.\s]+)/', $price_text, $matches);
return isset($matches[1]) ? floatval(str_replace(array(',', ' '), '', $matches[1])) : 0;
}
private function create_woo_product($product_data) {
$post_data = array(
'post_title' => $product_data['name'],
'post_content' => $product_data['description'],
'post_status' => 'draft',
'post_type' => 'product',
);
$product_id = wp_insert_post($post_data);
if ($product_id) {
// Устанавливаем цену
update_post_meta($product_id, '_regular_price', $product_data['price']);
update_post_meta($product_id, '_price', $product_data['price']);
// Устанавливаем тип товара
wp_set_object_terms($product_id, 'simple', 'product_type');
// Помечаем как импортированный
update_post_meta($product_id, '_firecrawl_imported', 'yes');
}
return $product_id;
}
}
// Инициализируем, если WooCommerce активен
if (class_exists('WooCommerce')) {
new FirecrawlWooCommerce();
}
?>
<?php
// Шорткоды для вставки динамического контента
add_shortcode('firecrawl_content', 'firecrawl_content_shortcode');
function firecrawl_content_shortcode($atts) {
$atts = shortcode_atts(array(
'url' => '',
'query' => '',
'limit' => 3,
'format' => 'list' // list, grid, simple
), $atts);
if (empty($atts['url']) && empty($atts['query'])) {
return '<p>Укажите URL или поисковый запрос</p>';
}
$firecrawl = new FirecrawlIntegration();
if (!empty($atts['url'])) {
// Парсим конкретный URL
$result = $firecrawl->scrape_content($atts['url']);
if ($result && $result['success']) {
return '<div class="firecrawl-content">' .
wp_kses_post($firecrawl->markdown_to_html($result['data']['markdown'])) .
'</div>';
}
} elseif (!empty($atts['query'])) {
// Поиск и отображение результатов
$results = $firecrawl->search_content($atts['query']);
if ($results && $results['success']) {
$output = '<div class="firecrawl-search-results">';
foreach (array_slice($results['data']['pages'], 0, $atts['limit']) as $page) {
if ($atts['format'] == 'grid') {
$output .= '<div class="firecrawl-item-grid">';
} else {
$output .= '<div class="firecrawl-item-list">';
}
$output .= '<h3><a href="' . esc_url($page['url']) . '" target="_blank">' .
esc_html($page['title']) . '</a></h3>';
$output .= '<p>' . esc_html($page['description']) . '</p>';
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
}
return '<p>Контент не найден</p>';
}
// CSS стили для шорткодов
add_action('wp_head', 'firecrawl_shortcode_styles');
function firecrawl_shortcode_styles() {
echo '<style>
.firecrawl-content {
border: 1px solid #ddd;
padding: 20px;
margin: 20px 0;
background: #f9f9f9;
}
.firecrawl-search-results {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.firecrawl-item-grid {
flex: 1 1 calc(33% - 20px);
border: 1px solid #eee;
padding: 15px;
background: white;
}
.firecrawl-item-list {
width: 100%;
border-bottom: 1px solid #eee;
padding: 15px 0;
}
.firecrawl-item-grid h3,
.firecrawl-item-list h3 {
margin-top: 0;
margin-bottom: 10px;
}
.firecrawl-item-grid a,
.firecrawl-item-list a {
text-decoration: none;
color: #0073aa;
}
</style>';
}
?>
[firecrawl_content url="https://example.com/article"]
[firecrawl_content query="новости ИИ" limit="5" format="grid"]
[firecrawl_content query="стартапы инвестиции" format="list"]
<?php
// В файлах темы
if (function_exists('firecrawl_content_shortcode')) {
echo do_shortcode('[firecrawl_content query="' . get_the_category()[0]->name . '" limit="3"]');
}
?>
// Хук для фильтрации импортируемого контента
add_filter('firecrawl_before_import', 'custom_content_filter', 10, 2);
function custom_content_filter($content, $source_url) {
// Исключаем контент с определенных доменов
$blocked_domains = array('spam-site.com', 'low-quality.org');
foreach ($blocked_domains as $domain) {
if (strpos($source_url, $domain) !== false) {
return false; // Не импортировать
}
}
// Проверяем минимальную длину
if (strlen($content['markdown']) < 500) {
return false;
}
return $content;
}
// Автоматическое заполнение SEO полей
add_action('save_post', 'firecrawl_seo_meta', 10, 2);
function firecrawl_seo_meta($post_id, $post) {
$source_url = get_post_meta($post_id, 'firecrawl_source_url', true);
if ($source_url) {
// Yoast SEO integration
if (function_exists('YoastSEO')) {
$description = get_post_meta($post_id, 'firecrawl_description', true);
if ($description) {
update_post_meta($post_id, '_yoast_wpseo_metadesc', $description);
}
}
// Canonical URL
update_post_meta($post_id, '_yoast_wpseo_canonical', $source_url);
}
}