bu her seferinde 2 kaynaktan çekecekmiş
Kod:Tümünü seç
$batch_size = 2; // Her istekte 2 kaynak işlenecek.
Kod:Tümünü seç
$batch_size = 1; // Her istekte 1 kaynak işlenecek.
Kod:Tümünü seç
<?php
/*
Plugin Name: Genel RSS Haber Scraper
Description: Excel benzeri tablo üzerinden RSS kaynaklarını ekleyip, RSS haberlerini çekmenize olanak tanır. Ayarlarda; RSS adresi, kategoriler, RSS haber etiket kodu, link eklenip eklenmeyeceği, resim HTML kodu ve bağlantı kontrolü yapabilirsiniz. Ayrıca, yazı içeriğinden cümle başları hariç büyük harfli olan ve en çok geçen kelimelerden otomatik 5 etiket oluşturur. Görsel URL’leri için <img src="..."> içindeki .jpg gibi URL’lerde, query string kısmı hariç çekilir.
Version: 1.1
Author: Örnek Geliştirici
License: GPL2
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Genel_RSS_Haber_Scraper {
private $option_name = 'genel_rss_haber_scraper_sources';
public function __construct() {
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_action( 'wp_ajax_genel_rss_scrape', array( $this, 'handle_scrape_request' ) );
add_action( 'wp_ajax_genel_rss_connection_check', array( $this, 'handle_connection_check' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'frontend_enqueue_scripts' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
}
public function add_admin_menu() {
add_menu_page(
'Genel RSS Haber Scraper',
'RSS Haber Scraper',
'manage_options',
'genel-rss-haber-scraper',
array( $this, 'admin_page' ),
'dashicons-rss',
20
);
}
public function register_settings() {
register_setting( 'genel_rss_haber_scraper_options', $this->option_name );
}
public function admin_enqueue_scripts( $hook ) {
if ( $hook == 'toplevel_page_genel-rss-haber-scraper' ) {
wp_enqueue_script(
'genel-rss-admin',
plugin_dir_url( __FILE__ ) . 'js/genel-rss-admin.js',
array( 'jquery' ),
'1.0',
true
);
wp_localize_script( 'genel-rss-admin', 'genelRssAdmin', array(
'ajax_url' => admin_url( 'admin-ajax.php' )
) );
}
}
public function frontend_enqueue_scripts() {
wp_enqueue_script(
'genel-rss-frontend',
plugin_dir_url( __FILE__ ) . 'js/genel-rss-frontend.js',
array( 'jquery' ),
'1.0',
true
);
wp_localize_script( 'genel-rss-frontend', 'genelRssAjax', array(
'ajax_url' => admin_url( 'admin-ajax.php' )
) );
}
public function admin_page() {
// Kayıtlı RSS kaynaklarını alıyoruz
$sources = get_option( $this->option_name, array() );
?>
<div class="wrap">
<h1>Genel RSS Haber Scraper</h1>
<form method="post" action="options.php">
<?php settings_fields( 'genel_rss_haber_scraper_options' ); ?>
<table class="widefat" id="rss-sources-table">
<thead>
<tr>
<th>RSS Adresi</th>
<th>Kategoriler (virgülle ayrılmış)</th>
<th>RSS Haber Etiket</th>
<th>Link Eklensin mi?</th>
<th>Resim HTML Kodu</th>
<th>Bağlantı Kontrol</th>
<th>İşlem</th>
</tr>
</thead>
<tbody>
<?php
if ( ! empty( $sources ) ) {
foreach ( $sources as $index => $source ) {
$rss_url = isset( $source['rss_url'] ) ? $source['rss_url'] : '';
$categories = isset( $source['categories'] ) ? $source['categories'] : '';
$tag = isset( $source['tag'] ) ? $source['tag'] : '';
$add_link = isset( $source['add_link'] ) ? $source['add_link'] : '';
$image_html = isset( $source['image_html'] ) ? $source['image_html'] : '';
?>
<tr>
<td>
<input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][rss_url]" value="<?php echo esc_attr( $rss_url ); ?>" size="40" />
</td>
<td>
<input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][categories]" value="<?php echo esc_attr( $categories ); ?>" size="30" placeholder="Kategori1,Kategori2" />
</td>
<td>
<input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][tag]" value="<?php echo esc_attr( $tag ); ?>" size="10" placeholder="item veya entry" />
</td>
<td>
<input type="checkbox" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][add_link]" value="1" <?php checked( $add_link, 1 ); ?> />
</td>
<td>
<input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][image_html]" value="<?php echo esc_attr( $image_html ); ?>" size="30" placeholder="<img src='...' />" />
</td>
<td>
<button class="button connection-check" data-row-index="<?php echo $index; ?>">Bağlantıyı Kontrol Et</button>
<span class="connection-result" id="conn-result-<?php echo $index; ?>"></span>
</td>
<td>
<button class="button remove-row">Kaldır</button>
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
<p>
<button type="button" class="button" id="add-row">Yeni Satır Ekle</button>
</p>
<?php submit_button(); ?>
</form>
<hr>
<h2>Manuel Haber Çekme (Batch Processing)</h2>
<p>RSS haberlerini çekmek için aşağıdaki butona tıklayın. İşlem, kaynakları parça parça (batch) kontrol ederek yapılır.</p>
<button id="fetch-rss-news" class="button button-primary">Haberleri Çek</button>
<div id="rss-news-log" style="margin-top:20px;padding:10px;background:#f9f9f9;border:1px solid #ddd;max-height:300px;overflow-y:auto;"></div>
<script>
jQuery(document).ready(function($) {
var log = $('#rss-news-log');
$('#fetch-rss-news').on('click', function() {
log.html('<p>Haber çekme işlemi başlatıldı...</p>');
processBatch(0);
});
function processBatch(offset) {
$.ajax({
url: ajaxurl,
type: 'POST',
data: { action: 'genel_rss_scrape', offset: offset },
success: function(response) {
if(response.success) {
log.append('<p style="color:green;">' + response.data.message + '</p>');
if(response.data.next_offset !== null) {
processBatch(response.data.next_offset);
} else {
log.append('<p style="font-weight:bold;">Tüm kaynaklar işlendi.</p>');
}
} else {
log.append('<p style="color:red;">' + response.data.message + '</p>');
}
},
error: function() {
log.append('<p style="color:red;">Bağlantı hatası!</p>');
}
});
}
});
</script>
</div>
<?php
}
// AJAX: Manuel haber çekme işlemi (batch processing)
public function handle_scrape_request() {
// Timeout ayarlarını optimize ediyoruz:
@set_time_limit(30);
ini_set('default_socket_timeout', 15);
$offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
$batch_size = 2; // Her istekte 2 kaynak işlenecek.
$result = $this->fetch_news_batch( $offset, $batch_size );
if ( $result['new_posts'] > 0 ) {
wp_send_json_success( array(
'message' => $result['new_posts'] . ' yeni haber eklendi.',
'next_offset' => $result['next_offset']
) );
} else {
wp_send_json_success( array(
'message' => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
'next_offset' => $result['next_offset']
) );
}
}
// AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
public function handle_connection_check() {
$rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
$tag = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';
if ( empty( $rss_url ) || empty( $tag ) ) {
wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
}
$rss_feed = @simplexml_load_file( $rss_url );
if ( ! $rss_feed ) {
wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
}
if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
} elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
} else {
wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
}
}
/**
* Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
*
* @param int $offset İşleme başlanacak kaynak indeksi.
* @param int $batch_size Bir istekte işlenecek kaynak sayısı.
* @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve bir sonraki offset.
*/
private function fetch_news_batch( $offset, $batch_size ) {
$sources = get_option( $this->option_name, array() );
$total = count( $sources );
if ( $total === 0 ) {
return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
}
$processed = 0;
$new_posts = 0;
for ( $i = $offset; $i < min( $offset + $batch_size, $total ); $i++ ) {
if ( $this->process_source( $sources[ $i ] ) ) {
$new_posts++;
}
$processed++;
}
$next_offset = $offset + $batch_size;
if ( $next_offset >= $total ) {
$next_offset = null;
}
return array(
'processed' => $processed,
'new_posts' => $new_posts,
'next_offset'=> $next_offset
);
}
/**
* Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
*
* @param array $source Kaynak bilgileri.
* @return bool Yeni haber eklenmişse true, aksi halde false.
*/
private function process_source( $source ) {
require_once( ABSPATH . 'wp-admin/includes/post.php' );
$rss_url = isset( $source['rss_url'] ) ? trim( $source['rss_url'] ) : '';
$categories_str = isset( $source['categories'] ) ? trim( $source['categories'] ) : '';
$tag = isset( $source['tag'] ) ? trim( $source['tag'] ) : '';
$add_link = isset( $source['add_link'] ) ? $source['add_link'] : 0;
$image_html = isset( $source['image_html'] ) ? trim( $source['image_html'] ) : '';
if ( empty( $rss_url ) || empty( $tag ) ) {
return false;
}
$rss_feed = @simplexml_load_file( $rss_url );
if ( ! $rss_feed ) {
error_log( 'RSS yüklenemedi: ' . $rss_url );
return false;
}
// --- RSS item yapısı ---
if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
foreach ( $rss_feed->channel->item as $item ) {
$title = (string) $item->title;
if ( post_exists( $title ) ) {
continue;
}
$link = (string) $item->link;
$description = (string) strip_tags( $item->description );
$content = isset( $item->children( 'content', true )->encoded ) ? (string) strip_tags( $item->children( 'content', true )->encoded ) : '';
$image_url = isset( $item->enclosure['url'] ) ? (string) $item->enclosure['url'] : '';
// Eğer enclosure yoksa description veya content içinden resim URL'si arayalım.
if ( empty( $image_url ) ) {
$combined_text = $description . ' ' . $content;
if ( preg_match( '/(https?:\/\/[^\s"\']+\.(?:png|jpg|wrp))(\?[^\s"\']*)?/i', $combined_text, $matches ) ) {
$image_url = $matches[1];
}
}
if ( empty( $title ) || ( empty( $content ) && empty( $description ) ) ) {
continue;
}
$post_content = '<p>' . esc_html( $description ) . '</p><p>' . esc_html( $content ) . '</p>';
if ( $add_link ) {
$post_content .= '<p><a href="' . esc_url( $link ) . '" target="_blank" rel="noopener noreferrer">Kaynak</a></p>';
}
$category_ids = array();
if ( ! empty( $categories_str ) ) {
$categories = array_map( 'trim', explode( ',', $categories_str ) );
foreach ( $categories as $cat_name ) {
$cat_id = get_cat_ID( $cat_name );
if ( ! $cat_id ) {
$cat_id = wp_create_category( $cat_name );
}
$category_ids[] = $cat_id;
}
}
$post_id = wp_insert_post( array(
'post_title' => wp_strip_all_tags( $title ),
'post_content' => $post_content,
'post_status' => 'publish',
'post_author' => 1,
'post_category' => $category_ids,
'post_type' => 'post'
) );
if ( ! is_wp_error( $post_id ) ) {
// Görsel ekleme işlemi
if ( ! empty( $image_url ) ) {
require_once( ABSPATH . 'wp-admin/includes/media.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attachment_id = media_sideload_image( $image_url, $post_id, $title, 'id' );
if ( ! is_wp_error( $attachment_id ) ) {
set_post_thumbnail( $post_id, $attachment_id );
}
}
// Ekstra resim HTML kodunu ekleme (varsa)
if ( ! empty( $image_html ) ) {
$post_content .= "\n" . $image_html;
wp_update_post( array(
'ID' => $post_id,
'post_content' => $post_content
) );
}
// Yazı içeriğinden otomatik etiket oluşturma (cümle başları hariç)
$tags = $this->extract_tags_from_content( $description . ' ' . $content );
if ( ! empty( $tags ) ) {
wp_set_post_tags( $post_id, $tags );
}
return true; // Bu kaynaktan bir haber eklendi.
}
}
}
// --- RSS entry yapısı ---
elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
foreach ( $rss_feed->entry as $entry ) {
$title = (string) $entry->title;
if ( post_exists( $title ) ) {
continue;
}
$link = '';
if ( isset( $entry->link ) ) {
foreach ( $entry->link as $l ) {
$attributes = $l->attributes();
if ( isset( $attributes['rel'] ) && (string) $attributes['rel'] === 'alternate' ) {
$link = (string) $attributes['href'];
break;
}
}
if ( empty( $link ) ) {
$link = (string) $entry->link;
}
}
$description = isset( $entry->summary ) ? (string) strip_tags( $entry->summary ) : '';
$content = isset( $entry->content ) ? (string) strip_tags( $entry->content ) : '';
$image_url = '';
if ( empty( $image_url ) ) {
$combined_text = $description . ' ' . $content;
if ( preg_match( '/(https?:\/\/[^\s"\']+\.(?:png|jpg|wrp))(\?[^\s"\']*)?/i', $combined_text, $matches ) ) {
$image_url = $matches[1];
}
}
if ( empty( $title ) || ( empty( $content ) && empty( $description ) ) ) {
continue;
}
$post_content = '<p>' . esc_html( $description ) . '</p><p>' . esc_html( $content ) . '</p>';
if ( $add_link ) {
$post_content .= '<p><a href="' . esc_url( $link ) . '" target="_blank" rel="noopener noreferrer">Kaynak</a></p>';
}
$category_ids = array();
if ( ! empty( $categories_str ) ) {
$categories = array_map( 'trim', explode( ',', $categories_str ) );
foreach ( $categories as $cat_name ) {
$cat_id = get_cat_ID( $cat_name );
if ( ! $cat_id ) {
$cat_id = wp_create_category( $cat_name );
}
$category_ids[] = $cat_id;
}
}
$post_id = wp_insert_post( array(
'post_title' => wp_strip_all_tags( $title ),
'post_content' => $post_content,
'post_status' => 'publish',
'post_author' => 1,
'post_category' => $category_ids,
'post_type' => 'post'
) );
if ( ! is_wp_error( $post_id ) ) {
if ( ! empty( $image_url ) ) {
require_once( ABSPATH . 'wp-admin/includes/media.php' );
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
$attachment_id = media_sideload_image( $image_url, $post_id, $title, 'id' );
if ( ! is_wp_error( $attachment_id ) ) {
set_post_thumbnail( $post_id, $attachment_id );
}
}
$tags = $this->extract_tags_from_content( $description . ' ' . $content );
if ( ! empty( $tags ) ) {
wp_set_post_tags( $post_id, $tags );
}
return true;
}
}
}
return false;
}
/**
* Yazı içeriğinden, cümle başları hariç, ilk kelimeyi atlayarak
* büyük harfli (ilk harfi büyük) kelimelerin frekansını hesaplar ve
* en çok geçen 5 kelimeyi etiket olarak döndürür.
*/
private function extract_tags_from_content( $content ) {
$sentences = preg_split( '/(?<=[.?!])\s+/', $content, -1, PREG_SPLIT_NO_EMPTY );
$words = array();
foreach ( $sentences as $sentence ) {
$sentence_words = preg_split( '/\s+/', $sentence, -1, PREG_SPLIT_NO_EMPTY );
if ( count( $sentence_words ) > 1 ) {
for ( $i = 1; $i < count( $sentence_words ); $i++ ) {
$words[] = $sentence_words[$i];
}
}
}
$filtered = array();
foreach ( $words as $word ) {
$clean = trim( $word, ".,!?()[]{}\"'" );
if ( strlen( $clean ) > 2 && ctype_upper( substr( $clean, 0, 1 ) ) ) {
$filtered[] = $clean;
}
}
$freq = array();
foreach ( $filtered as $w ) {
$key = strtolower( $w );
if ( isset( $freq[ $key ] ) ) {
$freq[ $key ]++;
} else {
$freq[ $key ] = 1;
}
}
arsort( $freq );
$top_tags = array_slice( array_keys( $freq ), 0, 5 );
return $top_tags;
}
}
new Genel_RSS_Haber_Scraper();