PhpQuery. Забираем данные с другого сайта

PhpQuery. Забираем данные с другого сайта

789
12.07.2017

Столкнулся я недавно с задачей переноса сайта с одной торговой площадки на 1С-Битрикс. Задача, в общем-то не сложная (должна быть) - на всех торговых площадках есть механизм выгрузки данных в формат xml или xls, или csv. И тут были все эти варианты, но! В этих файлах информации было очень мало: название товара, адрес товара и цена. Но т.к. задача стояла перенести сайт на битрикс, а не только перенести цены - такой формат нам не подошел.

В ходе длительных манипуляци процесс переноса был разбит на несколько составляющих частей:

  1. Для начала выгрузил каталог товаров в xlsx-файл
  2. Далее написал скрипт, позволяющий прочитать данные из полученного файла. Для этого воспользовался библиотекой PhpExcel, которая позволяет достаточно успешно работать с Excel-файлами. Написал функцию перебора всех строк полученного excel-файла. Данные из файла перевел в массив функцией библиотеки toArray.
  3. Дальше полученный массив с данными с помощью ajax-отправки данных запустил в обработку.

Вот обработка и оказалась очень интересной. Мне нужно было перенести более 9 тыс. товаров, вместе с ценами, всеми характеристиками, изображениями. Т.е. аяксом мы передавали вводную информацию по каждому товару, а дальше начиналась обработка.

Обработка каждой конкретной страницы сводилась к манипуляциям с dom-структурой карточки товара. Для этого была использована библиотека PhpQuery.

Сначала нужно считать весь текст со страницы в строковую переменную.

function GetCurlData($url)
	{
		$altUrl = '/' . str_replace('/', '_', substr($url, 1));
		if (file_exists($this->uploadFolder . $url))
		{
			return file_get_contents($this->uploadFolder . $url);
		} elseif (file_exists($this->uploadFolder . $altUrl))
		{
			return file_get_contents($this->uploadFolder . $altUrl);
		} else
		{
			$sourceFileHeaders = @get_headers($this->domain . $url);
			if(preg_match("|200|", $sourceFileHeaders[0])){
				$linkData = file_get_contents($this->domain . $url);
				if (strlen($linkData) > 0)
				{
					file_put_contents($this->uploadFolder . $altUrl, $linkData);
					return $linkData;
				} else
				{
					return false;
				}
			} else {
				echo 'ERROR WITH URL: ',$this->domain . $url;
			}
		}
	}

Основной фишкой тут является сохранение полученного тела страницы в локальный файл, чтобы не сердить администратора сервера-донора частыми запросами (я раза с 10 построил полную структуру получения всех данных со страницы).

Дальше - проводим инициализацию библиотеки phpquery:

require_once $_SERVER['DOCUMENT_ROOT'] . '/some_path/phpQuery-onefile.php';

И строим объект PhpQuery для дальнейшей работы:

$pageDoc = phpQuery::newDocument($pageData);

Дальше проходим по dom-структуре и получаем нужные данные, которые объединяем в одно целое и сохраняем в базу данных.


Пример кода с обработкой dom-данных для получения текста с подробным описанием товара.
	 $description = $pageDoc->find('div.tab-info div.description');
		foreach ($description->find('img') as $image)
		{
			$image = pq($image);
			$src = $image->attr('data-bx-image');
			if (strlen($src) > 0)
			{
				$image->removeAttr('data-bx-image');
			} else
			{
				$src = $image->attr('src');
			}
			$src = $this->GetForeignImage($src, md5($url) . '-');
			$image->attr('src', $src);
		}

		foreach ($description->find('a') as $link)
		{
			$link = pq($link);
			$link->attr('target', '_blank');
		}

		$description = $description->html();

		if(strlen($description)>0) $this->SaveToDB($description,$toID);

Данный код получает описание карточки товара, в описании вытягивает все изображения и сохраняет эти изображения локально со сменой ссылок на изображения в тексте описания. Также всем ссылкам добавлено открытие в новой вкладке (или можно их тут вообще удалить, или произвести кукую-то обработку). Функция обработки изображений, имеет вид:

function GetForeignImage($url,$hash=''){
		if(strlen($url)<=0) return $url;
		if(strpos($url,'http://')!==false || strpos($url,'https://')!==false){
			$image = file_get_contents($url);
		} else {
			$image = file_get_contents($this->domain.$url);
		}

		$imageName = pathinfo($url);
		$imageName = current(explode('?', $imageName['basename']));

		$hash = '/'.$hash;

		if (!file_exists($this->imagesFolder . $hash.$imageName))
			file_put_contents($this->imagesFolder . $hash.$imageName, $image);

		return $this->localImagesFolder.$hash.$imageName;
	}

Вот такой вот вышел интересный скрипт, но при обработке столкнулся с проблемой - сервер сайта-донора таки заблокировал обращения с нового сервера:( - просто все страницы стали отдавать капчу, которую нужно ввести:( Решением стало получение данных через прокси. Об этом читайте в следующей статье!



Благодарю за внимание! Делитесь вашими замечаниями в комментариях ниже.


P.S. Обращайтесь ко мне за приобретением лицензий и продлений на 1C-Битрикс "Управление сайтом", лицензий на облачную и коробочную версии Битрикс 24 а также за приобретением и внедрением готовых решений на базе 1С-Битрикс от партнеров. За более подробной информацией свяжитесь со мной любым удобным для вас способом


Комментарии

Еще никто не комментировал данную публикацию. Будьте первыми!

Добавить комментарий

captcha

Возврат к списку