[php] Автоматизация работы с addurl Яндекса

Статус
В этой теме нельзя размещать новые ответы.

wolgast

Профессор
Регистрация
8 Дек 2006
Сообщения
297
Реакции
35
Я уже как-то писал о том, как "разгадывать капчи"
а сейчас решил развить этот пример в что-то более практичное.

Цель: автоматизировать добавление страниц в addurl Яндекса (webmaster.yandex.ru)

Скрипт конечно же на PHP и для определения значений капчи я все также использую сервис anti-captcha.com.

Вперед…

Форма с данными отправляется на Для просмотра ссылки Войди или Зарегистрируйся

Принимаемые данные:

url => добавляемый url
key => идентификатор операции
rep => значение капчи​

Основная задача для нас - получить идентификатор операции. Это своего рода идентификатор сессии, только он не прячется в куках. Можно написать регулярное выражение, но я решил использовать одну известную мне полезную функцию

PHP:
    //возвращает то, что между $left и $right в $str
    function cut_str($str, $left, $right)
    {
    $str = substr(stristr($str, $left), strlen($left));
    $leftLen = strlen(stristr($str, $right));
    $leftLen = $leftLen ? -($leftLen) : strlen($str);
    $str = substr($str, 0, $leftLen);
    return $str;
    }
К примеру чтобы из вот этого

Код:
<input type=“hidden” name=“key” value=“41b8227dcc2c765d90386921797db4ca”>

вытащить идентификатор, использует функцию следующим образом

PHP:
$key = cut_str($data, ‘name=”key” value=”‘,’”‘);

Дальше идем за качпей. Ее получаем по адресу

http://captcha.yandex.net/image?key={идентификатор операции}​

Следующим шагом нужно определить значение этой капчи. Об этом я подробно писал раньше. Если значение капчи нам известно, то остается только отправить форму скрипту яндекса.

PHP:
$postdata = array(
    ‘url’ => $link,
    ‘key’ => $key,
    ‘rep’ => $captcha_value
    );

PHP:
$cap = geturl(”http://webmaster.yandex.ru/add.xml”,$postdata);

Вот и все. Кстате для этого метода нет необходимости использовать прокси т.к. капчи вводятся безошибочно, а значит и банить незачто!

Полный листинг:
PHP:
<?php
/*
 * Автор: koder
 * 13.02.09
 * 
 * Дополнительная информация
 * http://myseoincome.ru/2009/02/php_yandex_addurl/
 * 
 */
set_time_limit(0);
//ключь anti-captcha
$anti_captcha_key = '......';
//файлик с URLами
$urls = file('url.txt');
$i=1;
foreach ($urls as $link){ //получили адрес
	$data = geturl('http://webmaster.yandex.ru/');	
	$key = cut_str($data, 'name="key" value="','"'); //получили идентификатор сеанса
	$captcha = geturl('http://captcha.yandex.net/image?key='.$key); //слили капчу
	
	$postdata = array(
		'method'    => 'base64', 
		'key'       => $anti_captcha_key, 
		'body'      => base64_encode($captcha),
		'ext' 		=> 'jpg',
		'phrase'	=> 0,
		'regsense'	=> 0,
		'numeric'	=> 0,
		'min_len'	=> 0,
		'max_len'	=> 0
	);
	$rev = geturl("http://anti-captcha.com/in.php",$postdata); //отдали капчу антикапче
	
	if (substr($rev,0,2)=='OK'){
		$anti_captcha_id = substr($rev,3);
	}else{
		echo "Upload ERROR";
		exit;
	}
	sleep(20); //подождем 20сек. пока ее разгадают
	
	$postdata = array(
	    'key'       => $anti_captcha_key,
	    'action'    => 'get',
	    'id' 	=> $anti_captcha_id
	);
		
	$cap = geturl("http://anti-captcha.com/res.php",$postdata); //ответ от антикапчи	
	if (substr($cap,0,2)=='OK'){
		$captcha_value = substr($cap,3);
	}else{
		echo $cap;
		exit;
	}	

	$postdata = array(
		'url' => $link,
		'key' => $key,
		'rep' => $captcha_value
	);
	
	$cap = geturl("http://webmaster.yandex.ru/add.xml",$postdata); //спамим в яндекс
	
	echo $i.": ".$link.' - ';
	if (strpos($cap, 'успешно добавлен')){
		echo 'ok<br>';
	}elseif (strpos($cap, 'уже проиндексирован')){
		echo 'в индексе<br>';
	}elseif (strpos($cap, 'является зеркалом')){
		echo 'зеркало<br>';
	}elseif (strpos($cap, 'неверно указали цифровой код')){
		echo 'Captcha error<br>';
		$postdata = array(
		        'key'       => $anti_captcha_key, 
		        'action'    => 'reportbad',
		        'id' 		=> $anti_captcha_id			    
	        );		        			
		$cap = geturl("http://anti-captcha.com/res.php",$postdata);		
	}elseif (strpos($cap, 'robots.txt')){
		echo 'запрещен в файле robots.txt<br>';
	}elseif (strpos($cap, 'отличный от 200')){
		echo '404<br>';
	}elseif (strpos($cap, 'запрещен к индексированию')){
		echo 'ban<br>';		
	}else{		
		echo 'error<br>';
		//echo $cap;
		//exit;
	}
$i++;	
}

    //возвращает то, что между $left и $right в $str
	function cut_str($str, $left, $right)
	{
		$str = substr(stristr($str, $left), strlen($left));
		$leftLen = strlen(stristr($str, $right));
		$leftLen = $leftLen ? -($leftLen) : strlen($str);
		$str = substr($str, 0, $leftLen);
		return $str;
	}
	
	
	function geturl($url,$postdata=0)
	{
		$poststr="";	
		if ($postdata)	
		while (list($name,$value)=each($postdata)){
    		if (strlen($poststr)>0) 
    			$poststr.="&";
    		$poststr.=$name."=".urlencode($value);
    	}
		// инициализация сеанса
		$ch = curl_init();		
		curl_setopt($ch, CURLOPT_URL, $url);		
		
		if ($postdata){
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $poststr);			
		}		
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3');
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		$res = curl_exec($ch);
		curl_close($ch);		
		return $res;
	}
		
?>


Архив со скриптом


 
PHP:
    //возвращает то, что между $left и $right в $str
    function cut_str($str, $left, $right)
    {
    $str = substr(stristr($str, $left), strlen($left));
    $leftLen = strlen(stristr($str, $right));
    $leftLen = $leftLen ? -($leftLen) : strlen($str);
    $str = substr($str, 0, $leftLen);
    return $str;
    }

полезная функция при парсинге всяком =)

я тоже юзаю ее в таком примерно виде:

PHP:
return (string)reset(explode($right, end(explode($left, $data))));

если ожидаешь число можно так:

PHP:
return (int)end(explode("ИЦ - ", $urls['Yandex CY']['Rank']));

обрежет все справа, кроме циферок, если не нашлось - вернет 0 :)
 
PHP:
$postdata = array(
        'method'    => 'base64', 
        'key'       => $anti_captcha_key, 
        'body'      => base64_encode($captcha),
        'ext'         => 'jpg',
        'phrase'    => 0,
        'regsense'    => 0,
        'numeric'    => 0,
        'min_len'    => 0,
        'max_len'    => 0
    );
    $rev = geturl("http://anti-captcha.com/in.php",$postdata); //отдали капчу антикапче
    
    if (substr($rev,0,2)=='OK'){
        $anti_captcha_id = substr($rev,3);
    }else{
        echo "Upload ERROR";
        exit;
    }
    sleep(20); //подождем 20сек. пока ее разгадают
    
    $postdata = array(
        'key'       => $anti_captcha_key,
        'action'    => 'get',
        'id'     => $anti_captcha_id
    );
        
    $cap = geturl("http://anti-captcha.com/res.php",$postdata); //ответ от антикапчи    
    if (substr($cap,0,2)=='OK'){
        $captcha_value = substr($cap,3);
    }else{
        echo $cap;
        exit;
    }
Эти все телодвижения лишние! :) Есть у антикапчи своя функция, она сама все сделает, нужно только с нужными параметрами её вызвать. Собственно вот она (вариант через сокеты:(
PHP:
function recognize($filename, $apikey, $is_verbose = true, $rtimeout = 5, $mtimeout = 120, $is_phrase = 0, $is_regsense = 0, $is_numeric = 0, $min_len = 0, $max_len = 0){
	if (!file_exists($filename)) {
		if ($is_verbose) echo "file $filename not found\n";
		return false;
	}
	$fp=fopen($filename,"r");
	if ($fp!=false) {
		$body="";
		while (!feof($fp)) $body.=fgets($fp,1024);
		fclose($fp);
		$ext=strtolower(substr($filename,strpos($filename,".")+1));
	}
	else {
		if ($is_verbose) echo "could not read file $filename\n";
		return false;
	}
	if ($ext=="jpg") $conttype="image/pjpeg";
	if ($ext=="gif") $conttype="image/gif";
	if ($ext=="png") $conttype="image/png";
	
	
	$sendhost="anti-captcha.com";
	$boundary="---------FGf4Fh3fdjGQ148fdh";
	$content="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"method\"\r\n";
	$content.="\r\n";
	$content.="post\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"key\"\r\n";
	$content.="\r\n";
	$content.="$apikey\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"phrase\"\r\n";
	$content.="\r\n";
	$content.="$is_phrase\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"regsense\"\r\n";
	$content.="\r\n";
	$content.="$is_regsense\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"numeric\"\r\n";
	$content.="\r\n";
	$content.="$is_numeric\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"min_len\"\r\n";
	$content.="\r\n";
	$content.="$min_len\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"max_len\"\r\n";
	$content.="\r\n";
	$content.="$max_len\r\n";
	$content.="--$boundary\r\n";
	$content.="Content-Disposition: form-data; name=\"file\"; filename=\"capcha.$ext\"\r\n";
	$content.="Content-Type: $conttype\r\n";
	$content.="\r\n";
	$content.=$body."\r\n"; //тело файла
	$content.="--$boundary--";
	
	$poststr="POST http://$sendhost/in.php HTTP/1.0\r\n";
	$poststr.="Content-Type: multipart/form-data; boundary=$boundary\r\n";
	$poststr.="Host: $sendhost\r\n";
	$poststr.="Content-Length: ".strlen($content)."\r\n\r\n";
	$poststr.=$content;
	// echo $poststr;
	
	if ($is_verbose) echo "connecting $sendhost...";
	$fp=fsockopen($sendhost,80,$errno,$errstr,30);
	if ($fp!=false) {
		if ($is_verbose) echo "OK\n";
		if ($is_verbose) echo "sending request ".strlen($poststr)." bytes...";
		fputs($fp,$poststr);
		if ($is_verbose) echo "OK\n";
		if ($is_verbose) echo "getting response...";
		$resp="";
		while (!feof($fp)) $resp.=fgets($fp,1024);
		fclose($fp);
		$result=substr($resp,strpos($resp,"\r\n\r\n")+4);
		if ($is_verbose) echo "OK\n";
	}
	else {
		if ($is_verbose) echo "could not connect to anti-captcha\n";
		if ($is_verbose) echo "socket error: $errno ( $errstr )\n";
		return false;
	}
	if (strpos($result, "ERROR")!==false or strpos($result, "<HTML>")!==false) {
		if ($is_verbose) echo "server returned error: $result\n";
		return false;
	}
	else {
		$ex = explode("|", $result);
		global $captcha_id;
		$captcha_id = $ex[1];
		if ($is_verbose) echo "captcha sent, got captcha ID $captcha_id\n";
		$waittime = 0;
		if ($is_verbose) echo "waiting for $rtimeout seconds\n";
		sleep($rtimeout);
		while(true) {
			$result = file_get_contents('http://anti-captcha.com/res.php?key='.$apikey.'&action=get&id='.$captcha_id);
			if (strpos($result, 'ERROR')!==false) {
				if ($is_verbose) echo "server returned error: $result\n";
				return false;
			}
			if ($result=="CAPCHA_NOT_READY") {
				if ($is_verbose) echo "captcha is not ready yet\n";
				$waittime += $rtimeout;
				if ($waittime>$mtimeout) {
					if ($is_verbose) echo "timelimit ($mtimeout) hit\n";
            		break;
            	}
        		if ($is_verbose) echo "waiting for $rtimeout seconds\n";
            	sleep($rtimeout);
            }
            else {
            	$ex = explode('|', $result);
            	if (trim($ex[0])=='OK') return trim($ex[1]);
            }
        }
        
        return false;
    }
}
А вызываем так:
PHP:
$captcha = recognize($filename, $apikey, false, $rtimeout = 5, $mtimeout = 60);
можно еще несколько параметров добавить при вызове, их больше, это всего лишь пример, поясню - $filename - url капчи на локале, $apikey - ваш идентификатор на антикапче, true/false - показывать/не показывать сообщения о прцессе, $rtimeout - через каждые N сек получать ответ, и последний параметр в моем примере - таймаут для этой капчи.
PHP:
sleep(20); //подождем 20сек. пока ее разгадают
Не стоит ждать, надо запрашивать ответ постоянно, потому что у меня бывает за 5 секунд разгадывают, бывает дольше 20, время лучше не терять, это же автомат;)

Чуть не забыл (парсинг $key:(
PHP:
preg_match('|<input type=“hidden” name=“key” value=“(.*?)”>|is', $cap, $result);
$key = $result[1];
 
Скрипт можно совершенствовать до бесконечности. Я показал максимально облегченный вариант
 
  • Заблокирован
  • #5
я в php только новичок, при попытке запустить скрипт пишет
Fatal error: Call to undefined function curl_init() in C:\AppServ\www\yandex\index.php on line 114
На 114 строчке
PHP:
		$ch = curl_init();
Не знаю что делать, подскажите пожалуйста.
 
У тебя не установлен модуль php_curl
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху