Пишем простой парсер для WordPress

Привет всем в очередной раз!

Сегодня затрону тему написания парсеров для WordPress. Сразу скажу о том, что я не являюсь великим гуру в этом, но все же есть некий опыт и как говориться «делись с ближним» =)

Итак, есть задача организовать парсинг из сайта А (любой сайт, имеющий XML RSS ленту) на сайт B (под управлением CMS WordPress).

Шаг 1: Парсим XML Feed

В моем случае это был «www.unn.com.ua», он имеет так называемый RSS фид для каждой категории — мне нужна была определенная категория «Политика».
Я получил у них вот такой файл «http://www.unn.com.ua/rss/news_politics_ru.xml».

Спарсил его таким вот образом:

//RSS
$xml = parserXML('http://www.unn.com.ua/rss/news_politics_ru.xml');
//end

 //Парсю XML
function parserXML($url){
	$data = implode('',file($url)); 
	$parser = xml_parser_create(); 
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
    xml_parse_into_struct($parser, $data, $values, $tags); 
    xml_parser_free($parser); 
	 
	foreach ($tags as $key=>$values_arr)
	{ 
			if ($key == "item")
			{   
				for ($i=0; $i < count($values_arr); $i+=2) { 
					$offset = $values_arr[$i] + 1; 
					$len = $values_arr[$i + 1] - $offset;  
					$result_arr[] = (array_slice($values, $offset, $len)); 
				} 
			}else 
			{ 
				continue; 
			} 
	} 
	return @$result_arr;
}
//end

В результате мы получаем структурированные данные, которые можно перебрать с помощью foreach и получить каждую страницу полной новости из данного XML:

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [tag] => title
                    [type] => complete
                    [level] => 4
                    [value] => Кабмин сегодня планирует одобрить прогноз экономического и социального развития до 2021 года
                )

            [1] => Array
                (
                    [tag] => link
                    [type] => complete
                    [level] => 4
                    [value] => http://www.unn.com.ua/ru/news/1740619-kabmin-sogodni-planuye-skhvaliti-prognoz-ekonomichnogo-y-sotsialnogo-rozvitku-do-2021-roku
                )

            [2] => Array
                (
                    [tag] => category
                    [type] => complete
                    [level] => 4
                    [value] => Политика
                )

            [3] => Array
                (
                    [tag] => description
                    [type] => complete
                    [level] => 4
                    [value] => <p>Какое-то описание новости...</p>
                )

            [4] => Array
                (
                    [tag] => pubDate
                    [type] => complete
                    [level] => 4
                    [value] => Wed, 11 Jul 2018 09:44:13 +0300
                )

            [5] => Array
                (
                    [tag] => enclosure
                    [type] => complete
                    [level] => 4
                    [attributes] => Array
                        (
                            [length] => 2000
                            [url] => http://www.unn.com.ua/uploads/news/2018/07/11/d994ac961383ed8af7edc72fb4309eecd4a04906.jpg
                            [type] => image/jpeg
                        )

                )

        )

    [1] => Array
        (
...

Пример изъятия данныйх с такого массива очень прост:

$url = $data_item_arr[1][value]; //url 
к содержанию ↑

Шаг 2: Парсим url полной статьи

//Пример вызова этой функции
$result = parserHTML($url);

//Парсю полную новость unn.com.ua
function parserHTML($url)
{	//Достаю страницу полной статьи
	$data = file_get_contents($url);
	
	//Готовлю контент полной новости
	preg_match_all('/<div class="b-news-text b-static-text" itemprop="articleBody">(.*?)<\/div>/si', $data, $full_news_text);

	//Вырежу ссылки с участием сайта - донора
	$full_news_text = preg_replace ("!<a.*?href=\"?'?([^ \"'>]+)\"?'?.*?>(.*?)</a>!is", "\\2", $full_news_text[1][0]); 
	
	//Добавляю ссылку на источник
	$full_news_text .= '<p>Ссылка на источник: <a target="_blank" rel="nofollow noopener" href="'.donor_site_url.'" title="">'.donor_site_domain.'</a></p>';
	

	//Беру изображение полной новости из статьи донора
	preg_match_all('/<div class="b-news-full-img">(.*?)<\/div>/si', $data, $full_news_img);
	preg_match_all('/src="(.*?)"/si', $full_news_img[1][0], $full_news_img);
	
	//Достаю теги
	preg_match_all('/<div class="b-news-tags">(.*?)<\/div>/si', $data, $tags);
	//Вырежу ссылки с участием сайта - донора
	$tags = preg_replace ("!<a.*?href=\"?'?([^ \"'>]+)\"?'?.*?>(.*?)</a>!is", "\\2", $tags[1][0]); 
	$tags = str_replace('Теги:','', $tags);
	
	//Пакую в массив Полную статью и Картинку полной статьи
	$result = array('full_news_text'=>$full_news_text, 'full_news_img'=>$full_news_img[1][0], 'tags'=>$tags);

	return $result;
}
//end 

В результате мы получим массив, который будет содержать текст новости, полное изображение, а так же теги:

Array
(
    [full_news_text] => <p>Какая-то новость...</p>      
    [full_news_img] => /uploads/news/2018/07/11/760b2d870ede635daa9ab06d307b47f25f63ec85.jpg
    [tags] =>  экономика, Кабмин, Украина, Россия
)

к содержанию ↑

Шаг 3: Запись новости в WordPress с помощью API

//Загружаю библиотеки WordPress
require_once($_SERVER["DOCUMENT_ROOT"].'/wp-load.php' );
require_once($_SERVER["DOCUMENT_ROOT"].'/wp-admin/includes/image.php');
//end

//Добавляю запись WP
function addPostWP($post_title='', $post_content='', $post_status='publish', $post_author=1, $post_category = 1, $image_url='', $tags ='')
{   //Удаляю фильтры для добавляемого контента, дабы мог спокойно добавляться iframe из новости, так как часто попадались в контенте видео из Youtube.
    remove_filter('content_save_pre', 'wp_filter_post_kses'); 
    remove_filter('excerpt_save_pre', 'wp_filter_post_kses');
    remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');
	//Создаю массив с данными для записи
	$post_data = array(
		'post_title'    => wp_strip_all_tags($post_title), //Название статьи
		'post_content'  => $post_content, //Контент
		'post_status'   => $post_status, //Статус статьи
		'post_author'   => $post_author, //Автор (1 = Админ)
		'post_category' => array($post_category) //Ид категории
	);

	// Вставляем запись в базу данных и возвращаю ид нового поста
	$post_id = get_page_by_title($post_title, OBJECT, 'post');
	
	if($post_id->ID<1)
	{
		$post_id = wp_insert_post( $post_data );
	
	
		//Если есть картинка, креплю ее
		if((!empty($image_url)) && ($post_id > 0))
		{
			$attachment_id = Generate_Featured_Image( $image_url, $post_id  );
			
				//Добавляю теги;
				$tags_id = wp_set_post_tags( $post_id, $tags, true);
		}
		$result = array('post_id'=>$post_id,  'attachment_id'=>$attachment_id, 'tags_id'=>$tags_id);
	}else{
		$result = array('post_id'=>'Exist');
	}

	return $result;
}
//end

//Добавляю атачмент WordPress
function Generate_Featured_Image($image_url, $post_id)
{
    $upload_dir = wp_upload_dir();
    $image_data = file_get_contents($image_url);
    $filename = basename($image_url);
    if(wp_mkdir_p($upload_dir['path']))     $file = $upload_dir['path'] . '/' . $filename;
    else                                    $file = $upload_dir['basedir'] . '/' . $filename;
    file_put_contents($file, $image_data);

    $wp_filetype = wp_check_filetype($filename, null );
    $attachment = array(
        'post_mime_type' => $wp_filetype['type'],
        'post_title' => sanitize_file_name($filename),
        'post_content' => '',
        'post_status' => 'inherit'
    );
    $attach_id = wp_insert_attachment( $attachment, $file, $post_id );
   
    $attach_data = wp_generate_attachment_metadata( $attach_id, $file );
    $res1= wp_update_attachment_metadata( $attach_id, $attach_data );
    $res2= set_post_thumbnail( $post_id, $attach_id );
	return  $res2;
}
//end

Данное чудо возвращает в случае успешного добавления всех трех элементов (записи, картинки, тегов):

Array
(
    [0] => Array
        (
          
             [post_id] => 23
             [attachment_id] => 453
             [tags_id] => 4
        )
...

Данное чудо возвращает в случае если данный пост уже есть в базе (проверка по названию):

Array
(
    [0] => Array
        (
          
             [post_id] => Exist
        )
...

Во-всех остальных случаях, будет возвращены пустые значения предыдущего массива.

к содержанию ↑

Как таким парсером то пользоваться?

Очень просто, ставим файл с парсером на крон и получаем спокойно контент.

Скачать пример готового парсера «112.ua» для WordPress

Скачать на GitHub

[Всего голосов: 6    Средний: 3.8/5]