digitorum.ru

Как меня найти

Профиль

icq: 4415944

Обновляем статус в facebook php-скриптом

facebook, php

Для кода ниже потребуется curl, которого может и не быть у хостера, поэтому полной работоспособности у всех и вся не обещаю.

Класс Social_Larva_Exception - это просто обертка для Exception. В принципе его можно было и не делать, но мне оно как-то спокойнее с ним

<?php
	
	/*
	* (c) Pavel Ladygin (digitorum) http://digitorum.ru
	*/
	
	Class Social_Larva_Exception extends Exception {
		
		
	}
	
?>

 

Класс Social_Larva_Base - содержит все необходимое для парсинга страниц и отправки запросов к социальной сети.

<?php
	
	/*
	* (c) Pavel Ladygin (digitorum) http://digitorum.ru
	*/
	
	Class Social_Larva_Base {
		
		/*
		* Печеньки для запросов
		*/
		protected $_cookies = NULL;
		
		/*
		* Закэшированные данные
		*/
		protected $_cache = array();
		
		/*
		* Юзерагент
		*/
		protected $_userAgent = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7';
		
		/*
		* Базовое доменное имя
		*/
		protected $_baseDomain = '';
		
		/*
		* Базовый протокол
		*/
		protected $_baseProtocol = 'http';
		
		/*
		* Установить юзерагент
		*/
		public function setUserAgent($userAgent = '') {
			$this->_userAgent = $userAgent;
		}
		
		/*
		* Запомнить значение
		*/
		protected function _setCacheValue($key = '', $value = '') {
			$this->_cache[$key] = $value;
		}
		
		/*
		* Вспомнить значение
		*/
		protected function _getCacheValue($key = '') {
			 return isset($this->_cache[$key]) ? $this->_cache[$key] : false;
		}
		
		/*
		* Удалить кэш
		*/
		protected function _clearCache($key = '') {
			$this->_cache = array();
		}
		
		/*
		* Получить список печенегк из ответа
		*/
		protected function _getCookiesFromResponse($result) {
			$cookies = array();
			preg_match_all('~Set-Cookie:\s*([^;]+)~i', $result, $cookies);
			if(!count($cookies)) {
				return array();
			}
			return $cookies[1];
		}
		
		/*
		* Отправляем запрос
		*/
		protected function _sendRequest($options = array()) {
			$ch = curl_init();
			foreach($options as $option => $value) {
				curl_setopt($ch, $option, $value);
			}
		    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
		    curl_setopt($ch, CURLOPT_USERAGENT, $this->_userAgent);
		    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
		    $result = curl_exec($ch);
		    curl_close($ch);
			if ($result) {
				return $result;
			} else {
				throw new Social_Larva_Exception(curl_error($ch));
			}
		}
		
		/*
		* Получить форму со страницы
		*/
		protected function _getFormHtml($pageHtml, $formUniqueAttribute) {
			if(preg_match('~<form[^<]+' . $formUniqueAttribute . '.*?</form>~is', $pageHtml, $matches)) {
				return $matches[0];
			}
			return '';
		}
		
		/*
		* Получаем поля формы
		*/
		protected function _getFormFields($formHtml) {
			$fields = array();
			// пока забираем только инпуты
			preg_match_all('~<input[^>]+>~is', $formHtml, $matches);
			foreach($matches[0] as $match) {
				preg_match_all('~(<|name|type|value)[^\s]+~is', $match, $attributes);
				$tmp = array();
				foreach($attributes[0] as $attribute) {
					$attribute = explode("=", str_replace(array('\'', '"', '<'), array('','',''), $attribute));
					if(count($attribute) == 1) {
						$tmp['element'] = $attribute[0];
					} else {
						$tmp[$attribute[0]] = $attribute[1];
					}
				}
				if(isset($tmp['name']) && isset($tmp['element'])) {
					switch($tmp['element']) {
						case 'input' :
							if(isset($tmp['value'])) {
								$fields[$tmp['name']] = $tmp['value'];
							}
							break;
						default :
							break;
					}
					
				}
			}
			return $fields;
		}
		
		/*
		* Разбираем форму
		*/
		protected function _parseForm($formHtml = '') {
			$result = array(
				'fields' => $this->_getFormFields($formHtml),
				'action' => '',
				'method' => ''
			);
			if(preg_match_all('~(action=|method=).*?\s~is', $formHtml, $matches)) {
				foreach($matches[0] as $match) {
					$match = explode('=', str_replace(array('\'', '"'), array('', ''), $match), 2);
					if(count($match) == 2) {
						$result[strtolower($match[0])] = trim($match[1]);
					}
				}
			}
			if($result['method'] == '') {
				throw new Social_Larva_Exception('No request method detected');
			}
			if($result['action']  == '') {
				throw new Social_Larva_Exception('No form action detected');
			}
			$result['method'] = strtoupper($result['method']);
			if(!preg_match('~https?://~', $result['action'])) {
				$result['action'] = $this->_baseProtocol . '://' . $this->_baseDomain . $result['action'];
			}
			return $result;
		}
		
		/*
		* Получить главную страницу
		*/
		protected function _getMainPageHtml() {
			$url = $this->_baseProtocol . '://' . $this->_baseDomain;
			if(!$this->_getCacheValue($url)) {
				$this->_setCacheValue(
					$url,
					$this->_sendRequest(
						array(
							CURLOPT_URL => $url,
							CURLOPT_COOKIE => $this->_cookies
						)
					)
				);
			}
			return $this->_getCacheValue($url);
		}
		
	}
	
?>

 

Класс Social_Larva_Facebook - это уже непосредственно класс для работы с facebook.

<?php
	
	/*
	* (c) Pavel Ladygin (digitorum) http://digitorum.ru
	*/
	
	Class Social_Larva_Facebook extends Social_Larva_Base {
		
		/*
		* Базовое доменное имя
		*/
		protected $_baseDomain = 'www.facebook.com';
		
		/*
		* Конструктор
		*/
		public function __construct($email = '', $password = '') {
			$this->_login($email, $password);
		}
		
		/*
		* Деструктор
		*/
		public function __destruct() {
			$this->_logout();
		}
		
		/*
		* Авторизация
		*/
		private function _login($email = '', $password = '') {
			$form = $this->_parseForm($this->_getFormHtml($this->_getMainPageHtml(), 'login_form'));
			$form['fields']['email'] = $email;
			$form['fields']['pass'] = $password;
			$result = $this->_sendRequest(
				array(
					CURLOPT_URL => $form['action'],
					CURLOPT_HEADER => true,
					CURLOPT_NOBODY => true,
					CURLOPT_CUSTOMREQUEST => $form['method'],
					CURLOPT_POST => 1,
					CURLOPT_POSTFIELDS => http_build_query($form['fields']),
					CURLOPT_COOKIE => NULL
				)
			);
			$this->_cookies = $this->_getCookiesFromResponse($result);
			if(!count($this->_cookies)) {
				throw new Social_Larva_Exception('Can\'t receive cookies at first step authorization');
			}
			$this->_cookies = $this->_cookies[0];
			$result = $this->_sendRequest(
				array(
					CURLOPT_URL => $form['action'],
					CURLOPT_HEADER => true,
					CURLOPT_NOBODY => true,
					CURLOPT_CUSTOMREQUEST => $form['method'],
					CURLOPT_POST => 1,
					CURLOPT_POSTFIELDS => http_build_query($form['fields']),
					CURLOPT_COOKIE => $this->_cookies
				)
			);
			$this->_cookies = implode(';', $this->_getCookiesFromResponse($result));
			if(strpos($this->_cookies, 'c_user') === false) {
				// если не получилось авторизоваться - выбрасываем эксепшн
				throw new Social_Larva_Exception('Authorization failed');
			}
			// сбрасываем весь кэш после авторизации
			$this->_clearCache();
		}
		
		/*
		* Выход
		*/
		private function _logout() {
			if($this->_cookies !== NULL) {
				// ищем форму и поля в ней
				$form = $this->_parseForm($this->_getFormHtml($this->_getMainPageHtml(), 'logout_form'));
				// отправляем запрос
				$result = $this->_sendRequest(
					array(
						CURLOPT_URL => $form['action'],
						CURLOPT_HEADER => true,
						CURLOPT_CUSTOMREQUEST => $form['method'],
						CURLOPT_POST => 1,
						CURLOPT_POSTFIELDS => http_build_query($form['fields']),
						CURLOPT_COOKIE => $this->_cookies
					)
				);
				// смотрим не удалялась ли кука
				if(strpos($result, 'c_user=deleted') !== false) {
					$this->_cookies = NULL;
					$this->_clearCache();
					return true;
				}
			}
			return false;
		}
		
		/*
		* Обновить статус
		*/
		public function updateStatus($statusText = '', $privacy = false) {
			// ищем форму и поля в ней
			$form = $this->_parseForm($this->_getFormHtml($this->_getMainPageHtml(), '/ajax/updatestatus.php'));
			$form['fields']['xhpc_message'] = $statusText;
			$form['fields']['xhpc_message_text'] = $form['fields']['xhpc_message'];
			if($privacy) {
				switch(true) {
					case $privacy == 'Public' :
						$form['fields']['audience[0][value]'] = 80;
						break;
					case $privacy == 'Friends' :
						$form['fields']['audience[0][value]'] = 40;
						break;
					case $privacy == 'Only me' :
						$form['fields']['audience[0][value]'] = 10;
						break;
					default:
						$form['fields']['audience[0][value]'] = $privacy;
						break;
				}
			}
			// отправляем запрос
			$result = $this->_sendRequest(
				array(
					CURLOPT_URL => $form['action'],
					CURLOPT_HEADER => true,
					CURLOPT_NOBODY => false,
					CURLOPT_CUSTOMREQUEST => $form['method'],
					CURLOPT_POST => 1,
					CURLOPT_POSTFIELDS => http_build_query($form['fields']),
					CURLOPT_COOKIE => $this->_cookies
				)
			);
			// если статус обновился - есть локейшн в заголовках
			if(strpos($result, 'Location:') !== false) {
				return true;
			}
			return false;
		}
		
	}
	
?>

 

Код прозрачен и прокомментирован, поэтому останавливаться на его описании думаю не стоит.

Пример использования:

<?php
	try {
		
		$larva = new Social_Larva_Facebook('ваш@емэйл', 'пароль');
		$larva->updateStatus('Test', 'Only me');
		
	} catch (Social_Larva_Exception $e) {
		
		print $e->getMessage();
		
	}
?>

 

Ну и свидетельство того, что все работает:

Так же не стоит забывать о том, что facebook шибко умный, и в случае огромного количества запросов бан минут на 20 прилетает моментально 

Обновления на GitHub.