讓Python使用Bing翻譯API V2


 

 

最近要整點自動翻譯的東東,發現最親民的Google的翻譯API關閉了。那么擺在碼農的面前大概也只有2條路,

一是,直接使用web版本的的google翻譯,然后分析URL,和結果得到翻譯結果。然后直接調用,網上好像已經有兄弟們這樣干了。

二是,投奔微軟的陣營,使用Bing的API,

由於我要翻譯的東東好像在bing這兒的翻譯效果還可以,另外也訓練一下自己的Python能力,做點開源的事情。打算寫個Python使用Bing的API代碼測試一下。

Bing的翻譯API也不是絕對免費,每個月可以翻譯2M的字符的數據。這個當然不多,但一般人也夠用了。(純文本的聖經4M多)。超出后如果要再使用也必須付費,

費用好像是2M 40美刀。

另外Bing的API有一些有特色的地方,比如你可以在里面增加一些自己的翻譯,幫助修正你的翻譯結果,另外其還有語音能力。可以將你輸入的語音轉換為wav或者mp3文件。上流。

網上有些兄弟寫過Bing的API,但是大部分是是對於V1的版本的,V2版本改了驗證方式

現在微軟已經使用了新的驗證方式,使用APPID的方法已經玩不轉了。每次使用前必須用一個access token的東東,你必須自己申請一個ClientID和Client密碼。有興趣了解詳情的請參考

http://blogs.msdn.com/b/translation/p/gettingstarted1.aspx
http://api.microsofttranslator.com

 

Bing的API有3種調用接口,Ajax,SOAP,HTTP。我用Python搞,估計HTTP的方式更加合適我一點。我的只實現了部分接口,

我實現的Bing 翻譯V2的接口包括,翻譯,得到翻譯候選列表,(一次翻譯多個語句)設置翻譯內容,得到語音等幾個,其他的感覺有點多余,未必用得到。

如果沒有token或者Token超時,會自己重新去獲取Token,使用起來也比較簡單。

還是多說無益,上代碼,注釋應該足夠豐富,大家肯定看的明白。

 

  1 # coding=utf-8
  2 '''    
  3 網上有些兄弟寫過,但是大部分是是對於V1的版本的,V2版本改了驗證方式
  4 現在微軟已經使用了新的驗證方式,使用APPID的方法已經玩不轉了。必須用一個access token的東東
  5 
  6 清參考
  7 http://blogs.msdn.com/b/translation/p/gettingstarted1.aspx
  8 http://api.microsofttranslator.com
  9 
 10 '''
 11 
 12 import urllib
 13 import urllib2
 14 import json
 15 import time
 16 import unittest
 17 import xml.etree.ElementTree
 18 
 19 
 20 
 21 class Get_Translate_Data(object):
 22     '''
 23     Get Translate 操作取回的數據的,解析后的得到的數據字段,
 24     '''
 25     def __init__(self):
 26         # #翻譯結果匹配程度
 27         self._match_degree = 0
 28         # #翻譯結果被用戶選擇的次數
 29         self._selected_count = 0
 30         # #翻譯結果可以認可的比率,MS自己有一套規則,自己上參考網址看
 31         self._rating = 0
 32         # #返回的結果
 33         self._translated_text = ""
 34         
 35     def __str__(self):
 36         return ("match_degree:%s selected_count:%s rating:%s translated_text:%s")\
 37             % (self._match_degree, self._selected_count, self._rating, self._translated_text)
 38 
 39 
 40 class Bing_Translator_API(object):
 41     '''
 42           此工具用於使用bing的翻譯API,讓你快速的得到翻譯的結果
 43           我是按照2012年12月22日看到的API V2的要求實現的,
 44           實現的Bing 翻譯V2的接口包括,翻譯,得到翻譯候選列表,(一次翻譯多個語句)設置翻譯內容,得到語音,
 45     '''
 46     # 最大請求的字符長度,微軟的要求
 47     REQ_STR_MAX_LEN = 10000
 48     # add trascation 增加翻譯的原文最大長度
 49     ADD_ORIGINALTEXT_LEN = 1000
 50     # add trascation 增加翻譯的翻譯文字長度
 51     ADD_TRANSLATEDTEXT_LEN = 2000
 52     # SPEEK string的最大值
 53     SPEAK_STRING_LEN = 2000
 54     
 55     # 最大返回的結果個數
 56     RSP_RESULT_MAX_NUMBER = 10
 57     
 58     # 取得acess token的兩個參數,常量
 59     ACCESS_TOKEN_REQ_SCOPE = "http://api.microsofttranslator.com"
 60     ACCESS_TOKEN_REQ_GRANT_TYPE = "client_credentials"
 61     
 62     # POST取得ACESS TOKEN的URL
 63     ACCESS_TOKEN_REQ_URL = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"
 64     # GET方法得到翻譯的結果,只得到一個結果,估計這個最常用
 65     TRANSLATE_REQ_URL = "http://api.microsofttranslator.com/V2/Http.svc/Translate"
 66     # POST取得翻譯結果的結果的URL,這個是一次可以取回多個翻譯結果
 67     GET_TRANSLATE_REQ_URL = "http://api.microsofttranslator.com/V2/Http.svc/GetTranslations"
 68     # 檢測語句的語言
 69     DETECT_REQ_URL = "http://api.microsofttranslator.com/V2/Http.svc/Detect"
 70     # 增加翻譯的URL
 71     ADD_TRANSLATION_URL = "http://api.microsofttranslator.com/V2/Http.svc/AddTranslation"
 72     # 發音的請求
 73     SPEAK_REQ_URL = "http://api.microsofttranslator.com/V2/Http.svc/Speak"  
 74     
 75     # LC=language code,常用的幾個都寫在這兒,免得你還要查詢
 76     LC_CHINESE_SIMPLIFIED = "zh-CHS"
 77     LC_CHINESE_TRADITIONAL = "zh-CHT"
 78     LC_ENGLISH = "en"
 79     LC_JAPANESE = "ja"
 80     LC_KOREAN = "ko"
 81     LC_FRENCH = "fr"
 82     LC_GERMAN = "de"
 83     
 84     def __init__ (self, client_id, client_secret, proxy_conf=None):
 85         '''
 86         @param client_id 客戶端ID,你在MS網址注冊得到的ID
 87         @param client_secret 客戶端密鑰
 88         @param proxy_conf 代理配置,默認None,不配置,如果配置http,https都要寫,
 89                     比如{'http': 'http://proxy.a.com:8080/','https': 'http://proxy.a.com:8080/'},折騰了我一個下午
 90         '''
 91                 
 92         # 你請求獲得acess token的兩個參數,客戶端ID,和一個驗證密碼
 93         self._client_id = client_id
 94         self._client_secret = client_secret
 95         
 96         self._token_opener = None
 97         self._api_opener = None
 98         
 99         # 如果有代理,配置代理
100         if proxy_conf == None :
101             self._token_opener = urllib2.build_opener() 
102             self._api_opener = urllib2.build_opener()
103         else:
104             self._token_opener = urllib2.build_opener(urllib2.ProxyHandler(proxy_conf), urllib2.HTTPSHandler())
105             self._api_opener = urllib2.build_opener(urllib2.ProxyHandler(proxy_conf), urllib2.HTTPHandler())
106       
107         self._access_token = ""         
108         self._expires_time = 0
109       
110     
111 
112     
113     def __get_acess_token(self, retry_num=3):
114         '''
115         @brief 得到訪問的access token,如果已經有了token,而且沒有超時,就不繼續使用原有的token
116         @retry_num 重試的次數
117         '''
118         # 檢查超時與否,如果沒有超時,什么都不做
119         if (time.time() - 10 < self._expires_time):
120             return 0
121             
122         post_data = urllib.urlencode({'client_id':self._client_id, \
123                                       'client_secret':self._client_secret, \
124                                       'scope':Bing_Translator_API.ACCESS_TOKEN_REQ_SCOPE,
125                                       'grant_type':Bing_Translator_API.ACCESS_TOKEN_REQ_GRANT_TYPE })
126 
127         retry_count = 0 
128         resp_data = None
129         
130         # 進行N詞重試
131         while (retry_count < retry_num) :
132             try :        
133                 resp_data = self._token_opener.open(fullurl=Bing_Translator_API.ACCESS_TOKEN_REQ_URL, \
134                                                     data=post_data, \
135                                                     timeout=10)
136             except Exception, e:
137                 retry_count += 1
138                 self._token_opener.close()
139                 print str(e), Bing_Translator_API.ACCESS_TOKEN_REQ_URL, retry_count
140                 continue
141             break
142         
143         self._token_opener.close()
144         if (retry_count == retry_num):
145             return -1
146         
147         str_data = unicode(resp_data.read())
148         
149         # 分析json得到數據和超時時間,        
150         token_data = json.loads(str_data)
151         # 注意,不要解碼,我畫蛇添足的搞了1個小時才發現這個錯誤
152         self._access_token = token_data["access_token"]
153         self._expires_time = time.time() + int(token_data["expires_in"])
154                     
155         return 0
156     
157     def translate(self, from_language, to_language , want_translate, content_type="text/plain", category="general", retry_num=3):
158         '''
159         @brief 得到翻譯,只有一個翻譯結果,作為返回值返回,
160         @notice 這個方法使用的是GET 請求
161         @param from_language 翻譯的語言,參考前面的LC_XXX定義
162         @param to_language
163         @param want_translate 要翻譯的的文本信息,必須用UTF8的編碼,
164         @param content_type "text/plain" 或者"text/html"
165         @param category 分類,估計可以提高翻譯的准確度,但MS也沒有告知我們可以填寫啥,默認"general"
166         @return 一個元組,第一個數值是int,==0表示成功,第二個是成功后翻譯的語句,
167         '''
168         ret_text = ""
169 
170         if (len(want_translate) > Bing_Translator_API.REQ_STR_MAX_LEN):
171             return (-1, ret_text)
172         # 檢查token還是否有效,以及是否需要重新獲取
173         ret = self.__get_acess_token(retry_num)
174         if (ret != 0):
175             return (ret, ret_text)
176                 
177         # print self._api_opener.addheaders
178         # 得到請求的URL
179         url_all = Bing_Translator_API.TRANSLATE_REQ_URL + "?" + urllib.urlencode({'text':want_translate, \
180                                    'from':from_language, \
181                                    'to':to_language, \
182                                    'contentType':content_type, \
183                                    'category':category })
184         url_req = urllib2.Request(url=url_all)
185         url_req.add_header('Authorization', 'bearer ' + self._access_token)
186         
187         retry_count = 0 
188         resp_data = None
189         # 進行N次重試
190         while (retry_count < retry_num) :
191             try :        
192                 resp_data = self._token_opener.open(url_req, timeout=10)
193             except Exception, e:
194                 retry_count += 1
195                 print str(e), url_req, retry_count
196                 continue
197             else:
198                 break
199             finally:
200                 self._token_opener.close()
201                     
202         if (retry_count == retry_num):
203             return (-1, ret_text)
204         
205         # 解析XML結果得到數據
206         xml_str = resp_data.read()
207         tag = xml.etree.ElementTree.fromstring(xml_str)
208         ret_text = tag.text
209         
210         return (0, ret_text)
211      
212     def get_translate(self, from_language, to_language , want_translate, result_list, \
213                       content_type="text/plain", category="general", user="", uri="", retry_num=3):
214         '''
215         @brief 得到翻譯,可能有多個翻譯的結果返回,返回的是一個列表,
216         @notice 這個方法使用的是GET 請求
217         @param  result_list 返回參數,返回的翻譯list的Get_Translator_Data
218         @param  user 用戶名稱,默認為"",如果對翻譯效果不滿意,可以改為all
219         @param  uri  URI
220         @param 其他參數同translate函數,不多解釋
221         @return 返回0表示成功,其他表示失敗
222         '''
223         
224         if (len(want_translate) > Bing_Translator_API.REQ_STR_MAX_LEN):
225             return -1
226         # 檢查token還是否有效,以及是否需要重新獲取
227         ret = self.__get_acess_token(retry_num)
228         if (ret != 0):
229             return ret
230         
231         
232         # 得到請求的URL
233         url_all = Bing_Translator_API.GET_TRANSLATE_REQ_URL + "?" + urllib.urlencode({'text':want_translate, \
234                                    'from':from_language, \
235                                    'to':to_language, \
236                                    'maxTranslations':Bing_Translator_API.RSP_RESULT_MAX_NUMBER })
237         
238         # 其實不發送下面Post數據也可以發送請求(發送參數="",不能不寫,否則是GET請求),也可以得到結果,我測試過。增加下面這段反而又讓我調試了半天
239         # Post 請求的參數,里面的State是一個事務ID,請求帶過去,返回的結果,MS給你帶回來,你要希望使用,自己改造
240         # 這樣的到的翻譯很多,但效果感覺比較糟糕,估計有些是用戶添加的,如果你不喜歡,可以在User的值改為all
241         post_data = "<TranslateOptions xmlns=\"http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2\">"\
242                   "<Category>%s</Category>"\
243                   "<ContentType>%s</ContentType>"\
244                   "<ReservedFlags></ReservedFlags>"\
245                   "<State>20121221</State>"\
246                   "<Uri>%s</Uri>"\
247                   "<User>%s</User>"\
248                   "</TranslateOptions>" % (category, content_type, uri, user)
249         
250         
251         url_req = urllib2.Request(url=url_all, data=post_data)
252         url_req.add_header('Authorization', 'bearer ' + self._access_token)
253         # 如果要加post數據,這行必須加,否返回500的錯誤,看了半天C#的例子
254         url_req.add_header('Content-Type', 'text/xml')
255         retry_count = 0 
256         resp_data = None
257         # 進行N次重試
258         while (retry_count < retry_num) :
259             try :        
260                 resp_data = self._token_opener.open(url_req, timeout=10)
261             except Exception, e:
262                 retry_count += 1
263                 print str(e), url_req, retry_count
264                 continue
265             else:
266                 break
267             finally:
268                 self._token_opener.close()
269         
270         if (retry_count == retry_num):
271             return -1
272         
273         # 倒霉的XML namespace,麻煩死了
274         MS_GETTRNS_NAMESPACES = "http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2"
275         
276         xml_str = resp_data.read()
277         tag = xml.etree.ElementTree.fromstring(xml_str)
278         # 前面非要家那個.//,而且還必須有那個XML的名字空間{http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2}
279         tans_list = tag.findall(".//{%s}TranslationMatch" % MS_GETTRNS_NAMESPACES)
280         for tag_item in tans_list:
281             trans_data = Get_Translate_Data()
282             for iter_item in tag_item.iter():
283                 if iter_item.tag == "{%s}Count" % MS_GETTRNS_NAMESPACES:
284                     trans_data._selected_count = int(iter_item.text)
285                 if iter_item.tag == "{%s}MatchDegree" % MS_GETTRNS_NAMESPACES:
286                     trans_data._match_degree = int(iter_item.text)
287                 if iter_item.tag == "{%s}Rating" % MS_GETTRNS_NAMESPACES:
288                     trans_data._rating = int(iter_item.text)
289                 if iter_item.tag == "{%s}TranslatedText" % MS_GETTRNS_NAMESPACES:
290                     trans_data._translated_text = iter_item.text
291             # print trans_data
292             result_list.append(trans_data)
293         return 0
294             
295     def detect(self, detect_text, retry_num=3):
296         '''
297         @brief 檢查語句的語言
298         @notice 這個方法使用的是GET 請求
299         @param detect_text 檢測的語句,必須用UTF8的編碼,
300         @return 一個元組,第一個數值是int,==0表示成功,否則表示失敗,第二個是成功后返回語言的標識,如果失敗,返回''
301         '''
302         ret_text = ""
303 
304         if (len(detect_text) > Bing_Translator_API.REQ_STR_MAX_LEN):
305             return (-1, ret_text)
306         # 檢查token還是否有效,以及是否需要重新獲取
307         ret = self.__get_acess_token(retry_num)
308         if (ret != 0):
309             return (ret, ret_text)
310                 
311         # print self._api_opener.addheaders
312         # 得到請求的URL
313         url_all = Bing_Translator_API.DETECT_REQ_URL + "?" + urllib.urlencode({'text':detect_text})
314         url_req = urllib2.Request(url=url_all)
315         url_req.add_header('Authorization', 'bearer ' + self._access_token)
316         
317         retry_count = 0 
318         resp_data = None
319         # 進行N次重試
320         while (retry_count < retry_num) :
321             try :        
322                 resp_data = self._token_opener.open(url_req, timeout=10)
323             except Exception, e:
324                 retry_count += 1
325                 print str(e), url_req, retry_count
326                 continue
327             else:
328                 break
329             finally:
330                 self._token_opener.close()
331                     
332         if (retry_count == retry_num):
333             return (-1, ret_text)
334         
335         # 解析XML結果得到數據
336         xml_str = resp_data.read()
337         tag = xml.etree.ElementTree.fromstring(xml_str)
338         ret_text = tag.text
339         
340         return (0, ret_text)
341     
342     def add_translation(self, original_text, translated_text, from_language, to_language, user, \
343                         rating=1, content_type="text/plain", category="general", uri="", retry_num=3):
344         '''
345         @brief 增加翻譯內容,用於改善后面的翻譯
346         @notice 這個方法使用的是GET 請求
347         @param original_text 原文
348         @param translated_text 已經翻譯的原文
349         @param from_language 
350         @param to_language
351         @param usr 用戶名稱,估計在get的時候會有一些作用   
352         @param rating -10~10
353         @param content_type "text/plain" 或者"text/html"
354         @param category 分類,估計可以提高翻譯的准確度,但MS也沒有告知我們可以填寫啥,默認"general"
355         @param uri 
356         @param retry_num 重試次數
357         @return 返回0表示成功,其他表示失敗
358         '''
359         
360         if (len(original_text) > Bing_Translator_API.ADD_ORIGINALTEXT_LEN):
361             return -1
362         if (len(translated_text) > Bing_Translator_API.ADD_TRANSLATEDTEXT_LEN):
363             return -1
364         # 檢查token還是否有效,以及是否需要重新獲取
365         ret = self.__get_acess_token(retry_num)
366         if (ret != 0):
367             return (ret, ret_text)
368                 
369         # print self._api_opener.addheaders
370         # 得到請求的URL
371         url_all = Bing_Translator_API.ADD_TRANSLATION_URL + "?" + urllib.urlencode({'originalText':original_text, \
372                                    'translatedText':translated_text, \
373                                    'from':from_language, \
374                                    'to':to_language, \
375                                    'rating':rating, \
376                                    'contentType':content_type, \
377                                    'category':category, \
378                                    'user':user,
379                                    'uri':uri })
380         url_req = urllib2.Request(url=url_all)
381         url_req.add_header('Authorization', 'bearer ' + self._access_token)
382         
383         retry_count = 0 
384         resp_data = None
385         # 進行N次重試
386         while (retry_count < retry_num) :
387             try :        
388                 resp_data = self._token_opener.open(url_req, timeout=10)
389             except Exception, e:
390                 retry_count += 1
391                 print str(e), url_req, retry_count
392                 continue
393             else:
394                 break
395             finally:
396                 self._token_opener.close()
397                     
398         if (retry_count == retry_num):
399             return -1
400         
401         return 0
402     
403     
404     def speak(self, speak_text, language, format="audio/wav", options="MinSize", retry_num=3):
405         '''
406         @brief 得到翻譯,可能有多個翻譯的結果返回,返回的是一個列表,
407         @notice 這個方法使用的是GET 請求
408         @param  speak_text 
409         @param  language 語言
410         @param  format 為 audio/wav 或者  audio/mp3
411         @param  options 為“MaxQuality” 或者 "MinSize"
412         @return 返回0表示成功,其他表示失敗
413         '''
414         
415         if (len(speak_text) > Bing_Translator_API.SPEAK_STRING_LEN):
416             return -1
417         # 檢查token還是否有效,以及是否需要重新獲取
418         ret = self.__get_acess_token(retry_num)
419         if (ret != 0):
420             return ret
421         
422         ret_speak = ""
423         # 得到請求的URL
424         url_all = Bing_Translator_API.SPEAK_REQ_URL + "?" + urllib.urlencode({'text':speak_text, \
425                                    'language':language, \
426                                    'format':format, \
427                                    'options':options })
428         url_req = urllib2.Request(url=url_all)
429         url_req.add_header('Authorization', 'bearer ' + self._access_token)
430         
431         retry_count = 0 
432         resp_data = None
433         # 進行N次重試
434         while (retry_count < retry_num) :
435             try :        
436                 resp_data = self._token_opener.open(url_req, timeout=10)
437             except Exception, e:
438                 retry_count += 1
439                 print str(e), url_req, retry_count
440                 continue
441             else:
442                 break
443             finally:
444                 self._token_opener.close()
445                     
446         if (retry_count == retry_num):
447             return (-1, ret_speak)
448         
449         # 解析XML結果得到數據
450         ret_speak = resp_data.read()
451                 
452         return (0, ret_speak)
453 
454 #單元測試,單元測試
455 class Test_Bing_Translator_API(unittest.TestCase):
456 
457     def setUp(self):
458         # self._test_api = Bing_Translator_API(client_id="你的客戶端ID",\
459         #                                    client_secret="你的客戶端密鑰")
460         self._test_api = Bing_Translator_API(client_id="你的客戶端ID", \
461                                             client_secret="你的客戶端密鑰", \
462                                             proxy_conf={'http': '你的代理服務器:端口/', 'https': '你的代理服務器:端口'})
463 464 465 def test_translate(self): 466 ret, trans_str = self._test_api.translate(Bing_Translator_API.LC_CHINESE_SIMPLIFIED, \ 467 Bing_Translator_API.LC_ENGLISH, \ 468 "中華人民共和國"); 469 print ret , trans_str 470 471 test_string = "中華人民共和國" 472 test_gb2312 = test_string.encode('gb2312') 473 # 這個地方翻譯會錯誤,所以編碼不能用GB2312這類編碼 474 ret, trans_str = self._test_api.translate(Bing_Translator_API.LC_CHINESE_SIMPLIFIED, \ 475 Bing_Translator_API.LC_ENGLISH, \ 476 test_gb2312); 477 print ret , trans_str 478 479 def test_get_translate(self): 480 result_list = [] 481 ret = self._test_api.get_translate(Bing_Translator_API.LC_CHINESE_SIMPLIFIED, \ 482 Bing_Translator_API.LC_ENGLISH, \ 483 "中華人民共和國", 484 result_list); 485 for trans_data in result_list : 486 print trans_data 487 result_list = [] 488 ret = self._test_api.get_translate(Bing_Translator_API.LC_ENGLISH, \ 489 Bing_Translator_API.LC_CHINESE_SIMPLIFIED, \ 490 "to", 491 result_list); 492 for trans_data in result_list : 493 print trans_data 494 495 def test_detect(self): 496 ret, detect_lan = self._test_api.detect("中華人民共和國") 497 print ret, detect_lan 498 ret, detect_lan = self._test_api.detect("made in china") 499 print ret, detect_lan 500 501 def test_add_translation(self): 502 ret = self._test_api.add_translation(original_text="china", \ 503 translated_text="瓷器", \ 504 from_language=Bing_Translator_API.LC_ENGLISH, \ 505 to_language=Bing_Translator_API.LC_CHINESE_SIMPLIFIED, \ 506 user="fullsail") 507 print ret 508 result_list = [] 509 ret = self._test_api.get_translate(Bing_Translator_API.LC_ENGLISH, \ 510 Bing_Translator_API.LC_CHINESE_SIMPLIFIED, \ 511 "china", 512 result_list, 513 user="fullsail"); 514 for trans_data in result_list : 515 print trans_data 516 517 518 def test_speek(self): 519 ret, ret_speak = self._test_api.speak(speak_text="人一走,茶就涼,是自然規律;人沒走,茶就涼,是世態炎涼。一杯茶,佛門看到的是禪,道家看到的是氣,儒家看到的是禮,商家看到的是利。茶說:我就是一杯水,給你的只是你的想像,你想什么,什么就是你。心即茶,茶即心。", \ 520 language=Bing_Translator_API.LC_CHINESE_SIMPLIFIED); 521 522 523 file_hdl = open("D:\\123.wav", "wb+") 524 file_hdl.write(ret_speak) 525 file_hdl.close() 526 527 528 if __name__ == '__main__': 529 unittest.main() 530

 


 

最早看python應該是8年前了,但直到最近2個月才使用,計算機是實踐科學,看了不用,等於浪費,沒有任何效果 這次算是一個小小的進步。

 

【本文作者是雁渡寒潭,本着自由的精神,你可以在無盈利的情況完整轉載此文檔,轉載時請附上BLOG鏈接:http://www.cnblogs.com/fullsail/ 或者http://blog.csdn.net/fullsail,否則每字一元,每圖一百不講價。對Baidu文庫。360doc加價一倍】

想得卻不可得 你奈人生何 該捨的捨不得 只顧著跟往事瞎扯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM