Google Translate

28 Август 2008

Сейчас пытаюсь возродить свой бывший сайт под названием ForbidenWish. Там много книг и вносить их в БД вручную я не собираюсь, поэтому написал небольшой скрипт который обходит директории, парсит имена файлов и заносит их в базу. Вот в один момент я понял что простая транслитерация названия книги это не интересно, а иногда и глупо получалось, и я вспомнил про форум ДКлаб у них там при создании темы заголовок переводиться на английски (причем весьма неплохо) и подставляется в url. Я практически уверен что Котеров не писал переводчик и просто пользуется каким-то сервисом, первое что мне пришло в голову - Google. Сначала думал парсить html страницу но потом понял что там все намного проще и перевод забирается javascript'ом, В общем после непродолжительных изысканий я придумал вот эту функцю.


function translate($str, $from='ru', $to='en'){
	$fp = fsockopen("www.google.com", 80, $errno, $errstr, 30);
	if (!$fp) {
		trigger_error("$errstr ($errno)<br />\n", E_USER_WARNING);
		return "";
	} else {
		$out = "GET /translate_a/t?client=t&sl=".$from."&tl=".$to."&text=".urlencode($str)." HTTP/1.1\r\n";
		$out .= "Host: www.google.com\r\n";
		$out .= "User-Agent: Mozilla/5.0\r\n";
		$out .= "Accept-Encoding: deflate\r\n";
		$out .= "Connection: Close\r\n\r\n";
		
		fputs($fp, $out);
		$res = "";
		while (!feof($fp)) {
			$res .=  fgets($fp, 1024);
		}
		fclose($fp);
	}
	
	$res = explode("\r\n\r\n",$res);
	$res = explode("\r\n",$res[1]);
	return stripslashes(substr($res[1],1,-1));
}

Но таким образом гугл отказывается переводить больше чем 2 килобайта текста, если нудно переводить большие объемы по нужно использовать пост запрос


function translate($str, $from='en', $to='ru'){
	$fp = fsockopen("www.google.com", 80, $errno, $errstr, 30);
	if (!$fp) {
		trigger_error("$errstr ($errno) \n", E_USER_WARNING);
		return "";
	} else {
		$text = "text=".urlencode($str);
		$out = "POST /translate_a/t?client=t&sl=".$from."&tl=".$to." HTTP/1.1\r\n";
		$out .= "Host: www.google.com\r\n";
		$out .= "User-Agent: Mozilla/5.0\r\n";
		$out .= "Accept-Encoding: deflate\r\n";
		$out .= "Content-length: ".strlen($text)."\r\n";
		$out .= "Connection: Close\r\n\r\n";
		$out .= $text;
		
		fputs($fp, $out);
		$res = "";
		while (!feof($fp)) {
			$res .=  fgets($fp, 1024);
		}
		fclose($fp);
	}
	
	$res = explode("\r\n\r\n",$res);
	$res = explode("\r\n",$res[1]);
	return stripslashes(substr($res[1],1,-1));
}

Так можно обработать до 32 килобайт за раз!

Если кому пригодиться - оставьте коммент!

UPD Реализация на С++ от Lupascu Ion с небольшой доработкой от меня


String GoogleTranslator::TranslateText(String from, String to){
	//... need to add proxy
	//http_client.Proxy("");
	String url = "www.google.com/translate_a/t?client=t&sl=" + from + "&tl=" + to + "&ie=utf-8&oe=utf-8";
	http_client.URL(url);
	//http_client.Agent("Mozilla/5.0");
	http_client.TimeoutMsecs(5000);
	http_client.Post();
	http_client.PostData(String("text=").Cat()<<UrlEncode(inputwindow.textfrom.Get(CHARSET_UTF8)));
	//http_client.Headers("Accept-Encoding: deflate\r\n");
	String result = http_client.ExecuteRedirect();
	
	if (!IsNull(result)){
		if(result.StartsWith("\"")){// is string
			result.Remove(0, 1);
			result.Remove(result.GetLength()-1, 1);
		}
		else{ // is terms
			//... need to parse terms
		};
		
		return result;
	}
	else
		return String("Error:").Cat()<<Nvl(http_client.GetError(), "")
			<<"\n, status: "<<http_client.GetStatusCode()<<", "<<http_client.GetStatusLine()
			<<"\n, header: "<<http_client.GetHeaders();
}

UPD Есть предложение вместо


return stripslashes(substr($res[1],1,-1));
возвращать

return json_decode($res[1]);
Но на этом сраном хостинге с тех пор как им занимается компания HostBizUa перестали ставить свежие версии ПО, и у меня стоит древний PHP 5.1.6 в котором этой функции нет, поэтому я использую такое мудачество чтобы со словарем проблем не было.

return substr($res[1],0,1) == '[' ?
	substr($res[1],2,strpos($res[1],'"',2)-2) :
	substr($res[1],1,-1);
  1. 11 Апрель 2009 в 00:50 | #1
    я не знаю в чем может быть дело... посмотри настройки php например post_max_size хотя это на прием а не на отдачу. врядли я тебе с этим помогу
  2. 11 Апрель 2009 в 00:55 | #2
    У тебя весь текст возвращается?
  3. 11 Апрель 2009 в 00:58 | #3
    да, а в конце еще своего дописывает три абзаца :D
  4. 11 Апрель 2009 в 01:00 | #4
    ща попробую до post_max_size добраться.......ибо не искал на вдс:)
  5. 11 Апрель 2009 в 01:03 | #5
    все я спать пабрел а то у меня уже два ночи
  6. 11 Апрель 2009 в 01:05 | #6
    Давай......завтра вечером попробую отписаться:) спасибо за помощь....
  7. 11 Апрель 2009 в 01:07 | #7
    пажалусто :) удачи тебе!
  8. 11 Апрель 2009 в 01:32 | #8
    post_max_size поменял....всё равно мозг парит....не хочет весь текст до меня доходить:(
  9. 11 Апрель 2009 в 01:47 | #9
    кстати если вместо этого: $res = explode("\r\n\r\n",$res); $res = explode("\r\n",$res[1]); return stripslashes(substr($res[1],1,-1)); пишу: return stripslashes($res); доходит всё, даже более того......
  10. 11 Апрель 2009 в 21:19 | #10
    Всё равно нихера не пашет....текст возвращается только половина....ну или до какого-то определённого момента.... post_max_size = 16Mb не спас....
  11. 11 Апрель 2009 в 21:23 | #11
    Мож потому, что я оперой юзаю..........и через proxy.......хотя какая нафиг разница.......
  12. 12 Апрель 2009 в 08:41 | #12
    Я нашёл в чём фигня... Если вместо этого:
    
    $res = explode("\r\n\r\n",$res);
    	$res = explode("\r\n",$res[1]);
    	return stripslashes(substr($res[1],1,-1));
    Написать так:
    return stripslashes($res);
    
    То всё норм переводится, только HTTP заголовок(и) не режется.... т.е. надо лишнее убрать:
    HTTP/1.1 200 OK 
    Date: Sun, 12 Apr 2009 06:36:38 GMT 
    Expires: Sun, 12 Apr 2009 06:36:38 GMT 
    Cache-Control: private, max-age=86400 
    Content-Type: text/plain; charset=UTF-8 
    Content-Language: ru 
    Set-Cookie: PREF=ID=c8e93902a841c3a5:TM=1239518198:LM=1239518199:S=Y8p8WHj7Qqi3Btfb; expires=Tue, 12-Apr-2011 06:36:39 GMT; path=/; domain=.google.com Server: translation 
    Transfer-Encoding: chunked Connection: close fef "
    [text]
    " 0
    
    И между кусками в 2 байта приблизительно влезает кака-то хрень....(несколько символов...) В таком случае доходит весь перевод, и не режется... Помогите плз отделить норм текст от заголовка и прочей х...ни....
  13. 12 Апрель 2009 в 09:40 | #13
    http заголовки отделяються от текста двумя обрывами стоки "\r\n\r\n" попробуй substring
  14. 12 Апрель 2009 в 12:54 | #14
    а разрыв в тексте как можно убрать?:)
  15. 12 Апрель 2009 в 13:42 | #15
    а перед текстом выводится 'fef' ху из ит?
  16. 12 Апрель 2009 в 17:25 | #16
    Кароче вроде получилось.... поменял:
    
    $res = explode("\r\n\r\n",$res);
    $res = explode("\r\n",$res[1]);
    return stripslashes(substr($res[1],1,-1));
    
    на:
    
    $res = explode("\r\n\r\nfef",$res);
    return stripslashes(substr($res[1],1,-1));
    
    Ну и в результате менял 'nn' на '' Правда вначале стоит " и в конце "0, но не всегда...а так всё работает вроде...жаль идеально не получается....Спасибо за помощь
  17. 12 Апрель 2009 в 18:27 | #17
    нема за шо :)
  18. 12 Апрель 2009 в 19:20 | #18
    За скрипт....и помощь:))) шо ни паслал*)
  19. 12 Апрель 2009 в 19:53 | #19
    >>>шо ни паслал*) не говори глупостей :)
  20. 13 Апрель 2009 в 23:47 | #20
    Кста.....хотел спросить.... На чём у тя блог???:) Я вот тож хочу замутить уже давно....но чё-то руки не доходят.....мож расскажешь??? мыло у тя моё есть:)))
  21. Lupascu Ion
    19 Май 2009 в 09:54 | #21
    Хотелось добавить возможность интеграции механизма Google suggestion! Сечас пришло время вернуться на эту тему! Вопрос такой... кто-то решил эту задачу? Как решили? Я почти закончил маленкую программу каторую заменяет Abby. очень удобная и переводет с лубого приложение на нажатие клавиши [Ctrl]+[C]+[C]. Кому нужно... могу поделиться!
  22. 19 Май 2009 в 15:07 | #22
    я скорее всего не буду развивать дальше эту тему на пхп. если буду то на java и скорее всего для Android. то есть будет махонький плагин-переводчик_смсок
  23. Lupascu Ion
    19 Май 2009 в 15:30 | #23
    Я пишу на С++, для меня не важно на каком языке развивать... механизм самое главное! Я тестировал на Google Suggestion и в ответ ничего не получаю (ты новерно получил 200 ОК). хочу узнать если это правильно! Если да... то тогда могу поделиться с маленкую удобную программу!
  24. 19 Май 2009 в 15:34 | #24
    @Lupascu Ion я не знаю правильно это или нет((( нету док и нельзя проверить имперически((( так что все только на основе собственных наблюдений и догадок
  25. Mumr
    11 Июнь 2009 в 10:10 | #25
    Привет Я написал подобную функцию . мне надо CLR для SQL . Возник вопросик меня google заблокировал после несколько тысяч обращений, размеры текста не большие но много обращений .
    We're sorry... ... but your query looks similar to automated requests from a computer virus or spyware application. To protect our users, we can't process your request right now. We'll restore your access as quickly as possible, so try again soon. In the meantime, if you suspect that your computer or network has been infected, you might want to run a virus checker or spyware remover to make sure that your systems are free of viruses and other spurious software.
    Eсть какое-то ограничение? СПАСИБ
  26. 11 Июнь 2009 в 10:17 | #26
    @Mumr насколько я знаю, если постоянно к ним не ломиться то бан снимается в течении недели.
  27. Mumr
    11 Июнь 2009 в 16:55 | #27
    @CTAPbIu_MABP Короче пока рабочий раутер не перегрузят или пройдет неделя будем ждать. Всего то 100000 обрашений втечении часа и все . ;-) Спасиб
  28. 11 Июнь 2009 в 16:59 | #28
    100k за час это не мало.... я не удивлен что тебя забанили
  29. 11 Июнь 2009 в 16:59 | #29
    может подумали что ты их заддосить хочешь
  30. Mumr
    11 Июнь 2009 в 17:14 | #30
    @CTAPbIu_MABP Может Есть идеи типо прокси? Мне надо переодически переводить мнодо даты
  31. Mumr
    11 Июнь 2009 в 17:20 | #31
    @Mumr я ДБА и мне периодически надо загружать базы данных, с начальными данными для разработки. Я сохранил английский и понеобходимости для теста вношу на разных язиках
  32. 11 Июнь 2009 в 18:22 | #32
    посмотри пример от Lupascu Ion там только IP прокси вставить надо
  33. 14 Июнь 2009 в 17:55 | #33
    Попробуй задержку в 2 секунды поставить...мне помогло:) никакого бана и т.п. не последовало
  34. 14 Июнь 2009 в 22:21 | #34
    :)
  35. Mumr
    15 Июнь 2009 в 16:16 | #35
    Вроде попустило. Я закончил дебагить, так что запускаюсь периодически все путём. Максимум поставлю прокси. Спасиб за совет.
  36. 16 Июнь 2009 в 07:06 | #36
    эт хорошо:)
  37. 18 Август 2009 в 00:26 | #37
    Спасибо за скрипт ;)
  38. 18 Август 2009 в 01:48 | #38
    пожалуйста ;)
  39. Ion Lupascu
    18 Ноябрь 2009 в 11:16 | #39
    Привет, Вот на днях перестал работать метод get по адресу http://www.google.com/translate_a/t?client=t Может только для меня не работает? Знает ктонибудь какой новый адрес? Заранее спасибо!
  40. 18 Ноябрь 2009 в 12:35 | #40
    они же недавно полностью все API поменяли теперь надо обращатся на http://translate.google.com/translate_a/t?client=t&text=list
  41. Ion Lupascu
    18 Ноябрь 2009 в 14:31 | #41
    Методом get?
  42. Ion Lupascu
    18 Ноябрь 2009 в 14:49 | #42
    Извени, работает и старый вариант! просто они поменяли формат!!!
  43. 18 Ноябрь 2009 в 15:04 | #43
    не могу сейчас проверить ;)
  44. 30 Декабрь 2009 в 01:46 | #44
    Спасибо, тебе, Добрый Человек! А то через стандартный апи, большие тексты не переведёшь. Кстати, у меня так:
    
    $res = explode("\r\n\r\n",$res);
    $res = explode("\r\n",$res[1]);
    $json = json_decode($res[1].$res[3].$res[5].$res[7],true);
    $r="";
    for($i=0;$i<count($json[sentences]);$i++){
    	$r.=stripslashes($json[sentences][$i][trans]);
    }
    return $r;
    
  45. 30 Декабрь 2009 в 10:48 | #45
    пажалуста :) тока я немного не понял что там парсер скушал кавычки? [sentences]
  46. Pinocchio
    14 Январь 2010 в 14:09 | #46
    Первый вариант с GET-запросом больше не работает...
  47. 14 Январь 2010 в 14:53 | #47
    @Pinocchio что конкретно не работает
  48. Pinocchio
    26 Январь 2010 в 01:39 | #48
    Нет ответа от Гугла (как-то прикрыли). Не знаю, как сейчас, но на тот момент дня два не работало. У меня на сайте есть елемент, зависящий от google translate, поэтому чуть, что не так, пользователи жаловаться начинают. Пришлось заменить на второй вариант, там без проблем.
  49. Ion Lupascu
    26 Январь 2010 в 09:18 | #49
    От гугла все нормально! работает без проблем! у меня код в с++ и не имею проблем. В прочем не важно в чем пишешь код. самое главное работать с метод Get/set от http и правильно задать параметры!
  50. Alex
    11 Март 2010 в 16:04 | #50
    Господа! Я хочу в своем проекте на сайте (не на десктопе) использовать http://translate.google.com/translate_a/t?client=t&text=list , но , как я понял, официальный api вот такой: http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=hello%20world&q=goodbye&langpair=en|ru с гораздо более убогим ответом (только один вариант). Еще они требуют HEADER REFERER Вопрос: нормально ли реагирует гугл на использование неофиц api? Могут ли за это забанить и тд.? Еще у них есть api dictionary с возвратом озвученных слов в mp3. Какаие могут быть санкции, могут ли забанить весь проект? СПАСИБО.
Страницы комментариев
Комментирование отключено.