Translate.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Administrator
  5. * Date: 2019/4/24 0024
  6. * Time: 11:38
  7. */
  8. namespace App\Libs;
  9. class Translate
  10. {
  11. const APP_KEY = '52e2f13b4d5f16ea';
  12. const SEC_KEY = 'TFXmzOx3EwYhJoS1p1Fma2A4JkqPXjYO';
  13. const CURL_TIMEOUT = 2000;
  14. const URL = 'http://openapi.youdao.com/api';
  15. public function request(string $q)
  16. {
  17. $salt = $this->createGuid();
  18. $args = array(
  19. 'q' => $q,
  20. 'appKey' => self::APP_KEY,
  21. 'salt' => $salt,
  22. );
  23. $args['from'] = 'zh-CHS';
  24. $args['to'] = 'EN';
  25. $args['signType'] = 'v3';
  26. $curtime = strtotime("now");
  27. $args['curtime'] = $curtime;
  28. $signStr = self::APP_KEY . $this->truncate($q) . $salt . $curtime . self::SEC_KEY;
  29. $args['sign'] = hash("sha256", $signStr);
  30. $ret = $this->call(self::URL, $args);
  31. return $ret;
  32. }
  33. function bubbleSort($arr)
  34. {
  35. $len = count($arr);
  36. for ($i = 0; $i < $len - 1; $i++) {
  37. for ($j = 0; $j < $len - 1 - $i; $j++) {
  38. if (mb_strlen($arr[$j]['source']) < mb_strlen($arr[$j + 1]['source'])) {
  39. $tmp = $arr[$j];
  40. $arr[$j] = $arr[$j + 1];
  41. $arr[$j + 1] = $tmp;
  42. }
  43. }
  44. }
  45. return $arr;
  46. }
  47. public function htmlRequest(string $q)
  48. {
  49. $pattern = "/<tr.*?>(.*?)<\/tr>/is";
  50. $source_q = $q;
  51. $q = preg_replace($pattern, '', $q);//去掉表格
  52. $q = explode('翻译分割符', preg_replace('/(<.*?>)/', '翻译分割符', $q));
  53. $source_array = array();
  54. foreach ($q as $value) {
  55. $source = trim($value);
  56. if (!$source) continue;
  57. $source_target['source'] = $source;
  58. $source_target['source_q'] = $value;
  59. $source_array[] = $source_target;
  60. }
  61. foreach ($source_array as $inx => $val) {
  62. $data = json_decode($this->request($val['source']), true);
  63. $source_array[$inx]['target'] = $data['translation'][0] ?? '';
  64. }
  65. $this->bubbleSort(array_values($source_array));
  66. foreach ($source_array as $value) {
  67. $source_q = str_replace($value['source_q'], $value['target'], $source_q);
  68. }
  69. return $source_q;
  70. }
  71. protected function call($url, $args = null, $method = "post", $timeout = self::CURL_TIMEOUT, $headers = array())
  72. {
  73. $ret = false;
  74. $i = 0;
  75. while ($ret === false) {
  76. if ($i > 1)
  77. break;
  78. if ($i > 0) {
  79. sleep(1);
  80. }
  81. $ret = $this->callOnce($url, $args, $method, false, $timeout, $headers);
  82. $i++;
  83. }
  84. return $ret;
  85. }
  86. protected function callOnce($url, $args = null, $method = "post", $withCookie = false, $timeout = self:: CURL_TIMEOUT, $headers = array())
  87. {
  88. $ch = curl_init();
  89. if ($method == "post") {
  90. $data = $this->convert($args);
  91. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  92. curl_setopt($ch, CURLOPT_POST, 1);
  93. } else {
  94. $data = $this->convert($args);
  95. if ($data) {
  96. if (stripos($url, "?") > 0) {
  97. $url .= "&$data";
  98. } else {
  99. $url .= "?$data";
  100. }
  101. }
  102. }
  103. curl_setopt($ch, CURLOPT_URL, $url);
  104. curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  105. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  106. if (!empty($headers)) {
  107. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  108. }
  109. if ($withCookie) {
  110. curl_setopt($ch, CURLOPT_COOKIEJAR, $_COOKIE);
  111. }
  112. $r = curl_exec($ch);
  113. curl_close($ch);
  114. return $r;
  115. }
  116. protected function convert(&$args)
  117. {
  118. $data = '';
  119. if (is_array($args)) {
  120. foreach ($args as $key => $val) {
  121. if (is_array($val)) {
  122. foreach ($val as $k => $v) {
  123. $data .= $key . '[' . $k . ']=' . rawurlencode($v) . '&';
  124. }
  125. } else {
  126. $data .= "$key=" . rawurlencode($val) . "&";
  127. }
  128. }
  129. return trim($data, "&");
  130. }
  131. return $args;
  132. }
  133. protected function createGuid()
  134. {
  135. $microTime = microtime();
  136. list($a_dec, $a_sec) = explode(" ", $microTime);
  137. $dec_hex = dechex($a_dec * 1000000);
  138. $sec_hex = dechex($a_sec);
  139. $this->ensureLength($dec_hex, 5);
  140. $this->ensureLength($sec_hex, 6);
  141. $guid = "";
  142. $guid .= $dec_hex;
  143. $guid .= $this->create_guid_section(3);
  144. $guid .= '-';
  145. $guid .= $this->create_guid_section(4);
  146. $guid .= '-';
  147. $guid .= $this->create_guid_section(4);
  148. $guid .= '-';
  149. $guid .= $this->create_guid_section(4);
  150. $guid .= '-';
  151. $guid .= $sec_hex;
  152. $guid .= $this->create_guid_section(6);
  153. return $guid;
  154. }
  155. protected function create_guid_section($characters)
  156. {
  157. $return = "";
  158. for ($i = 0; $i < $characters; $i++) {
  159. $return .= dechex(mt_rand(0, 15));
  160. }
  161. return $return;
  162. }
  163. /**
  164. * 截断
  165. * @param $q
  166. * @return string
  167. */
  168. protected function truncate($q)
  169. {
  170. $len = mb_strlen($q);
  171. return $len <= 20 ? $q : (mb_substr($q, 0, 10) . $len . mb_substr($q, $len - 10, $len));
  172. }
  173. protected function ensureLength(&$string, $length)
  174. {
  175. $strLen = mb_strlen($string);
  176. if ($strLen < $length) {
  177. $string = str_pad($string, $length, "0");
  178. } else if ($strLen > $length) {
  179. $string = mb_substr($string, 0, $length);
  180. }
  181. }
  182. }