2016-12-21 12 views
0

Я пишу некоторый код для синтаксического анализа корейского текста с сервера, закодированного с помощью euc-kr корейского кодировщика.Быстрое кодирование euc-kr korean не работает. Но работает в python

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

В Python:

string = u'안녕하세요.'.encode('eucKR') 

В Swift:

let encoding:UInt = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(
     CFStringEncodings.EUC_KR.rawValue)) 

let encodedData = "안녕하세요.".data(using: String.Encoding(rawValue: encoding))! 

Что разница между этими 2 кодировках?

Ниже приведены полные исходные коды как для python, так и для swift. Я все еще придерживался кодирующей части. Является ли проблема связана с запросом на публикацию alamofire?

Python:

import requests 
from pattern import web 

string = u'저는 내일 바빠서 학교에 못갑니다.'.encode('eucKR') 
r = requests.post("http://nlp.korea.ac.kr/~demo/dglee/komatag.php", data={'formradio1': '', 'formradio2': 'ems', 'textarea': string}) 
dom = web.Element(r.text) 
main = dom('tr') 
for item in main: 
    result = web.plaintext(item.source) 
    a = result.encode('ISO-8859-1') 
    t=a.decode('eucKR') 
    print(t) 

Swift:

override func viewDidLoad() { 

     let string: NSString = NSString(string: "안녕하세요") 
     let encodedEucKr = stringToEuckrString(stringValue: string as String) 
     print(encodedEucKr) 

     Alamofire.request("http://nlp.korea.ac.kr/~demo/dglee/komatag.php", method: .post, parameters: ["formradio1":"", "formradio2":"ems", "textarea": encodedEucKr], headers: nil).responseString { response in 

      switch(response.result) { 
      case .success(_): 
       if let data = response.result.value{ 
        print(response.result.value) 
       } 
       break 

      case .failure(_): 
       print(response.result.error) 
       break 

      } 
     } 

    } 


func stringToEuckrString(stringValue: String) -> String { 

    let encoding:UInt = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(
     CFStringEncodings.EUC_KR.rawValue)) 

    let encodedData = stringValue.data(using: String.Encoding(rawValue: encoding))! 

    let attributedString = try? NSAttributedString(data: encodedData, options:[:],  documentAttributes: nil) 

    if let _ = attributedString { 
     return attributedString!.string 
    } else { 
     return "" 
    } 
} 
+0

Как вы проверили результаты? Насколько я могу проверить на Mac (Xcode 8.2.1 и python 2.7.10), оба результата содержали точно такую ​​же последовательность байтов. – OOPer

+0

Можете ли вы узнать, какое решение будет для моей проблемы? Я застрял на нем около 3 часов. до сих пор не повезло. –

+0

Ваш способ отправки запроса POST в EUC-KR является совершенно неправильным, но на данный момент у меня недостаточно времени для написания ответа. Подождите того, кто может вам помочь (или для меня, позже). Теперь ваш вопрос, похоже, готов к поиску пути решения вашей проблемы. – OOPer

ответ

0

Это было не просто по двум причинам ...

  1. Отправка данных формы в EUC-KR не считается стандартным в современных веб-технологиях и стандартах.

  2. Ответ, посланный с вашего сервера, является сломанным, что Swift не может декодировать результат как допустимый текст EUC-KR.

    (Это, кажется, ошибка вашего сервера кода на стороне.)

Во всяком случае, когда вам необходимо отправить запрос на основе веб-формы на сервер в EUC-KR:

  • Создайте последовательность байт EUC-KR от оригинала оригинала
  • Percent-денется, вам, возможно, придется сделать это самостоятельно
  • Поместите весь запрос в теле запроса HTTP
  • Добавить надлежащий заголовок типа mime

Некоторые детали зависят от сервера. Я никогда не использовал Alamofire, поэтому я не знаю, поддерживает ли Alamofire такие вещи.

Здесь я покажу вам пример, используя обычный URLSession:

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 
    sendRequest(string: "안녕하세요") 
} 

func sendRequest(string: String) { 
    let rawEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.EUC_KR.rawValue)) 
    let encoding = String.Encoding(rawValue: rawEncoding) 

    let url = URL(string: "http://nlp.korea.ac.kr/~demo/dglee/komatag.php")! 
    var request = URLRequest(url: url) 
    request.httpMethod = "POST" 
    //Create an EUC-KR byte sequece 
    let eucKRStringData = string.data(using: encoding) ?? Data() 
    //Percent-escape, you need to do it by yourself 
    //(Though, most server accepts non-escaped binary data with its own rule...) 
    let eucKRStringPercentEscaped = eucKRStringData.map {byte->String in 
     if byte >= UInt8(ascii: "A") && byte <= UInt8(ascii: "Z") 
     || byte >= UInt8(ascii: "a") && byte <= UInt8(ascii: "z") 
     || byte >= UInt8(ascii: "0") && byte <= UInt8(ascii: "9") 
     || byte == UInt8(ascii: "_") || byte == UInt8(ascii: ".") || byte == UInt8(ascii: "-") 
     { 
      return String(Character(UnicodeScalar(UInt32(byte))!)) 
     } else if byte == UInt8(ascii: " ") { 
      return "+" 
     } else { 
      return String(format: "%%%02X", byte) 
     } 
    }.joined() 
    //In application/x-www-form-urlencoded format, you send data in a URL-query like format. 
    let paramString = "formradio1=&formradio2=ems&textarea=\(eucKRStringPercentEscaped)" 
    //As all non-ASCII characters are percent-escaped, .isoLatin1 works well here. 
    let bodyData = paramString.data(using: .isoLatin1)! 
    //Form data needs to be sent as a body of HTTP protocol. 
    request.httpBody = bodyData 
    //Mime type for usual form data is "application/x-www-form-urlencoded". 
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 
    //URLRequest is ready and you can start dataTask here. 
    let task = URLSession.shared.dataTask(with: request) {data, response, error in 
     if let error = error { 
      print("Error:", error) 
     } 
     if let response = response { 
      print("Response:", response) 
     } 
     //The response may not be a valid EUC-KR, you need to decode it with acceptig invalid bytes. 
     if let data = data { 
      var result = "" 
      var i = 0 
      while i < data.count{ 
       let ch = data[i] 
       if ch < 0x80 { 
        result += String(Character(UnicodeScalar(UInt32(ch))!)) 
       } else if 
        i + 2 <= data.count, 
        let ch2 = String(data: data.subdata(in: i..<i+2), encoding: encoding) 
       { 
        result += ch2 
        i += 1 
       } else { 
        result += "?" 
       } 
       i += 1 
      } 
      print("Result:", result) 
     } 
    } 
    //Do not remember to resume the created task. 
    task.resume() 
    //And remember you should not do anything after you invoked an async task. 
} 

Если на стороне сервера может обрабатывать UTF-8 запросов и ответов правильно, приведенный выше код может быть гораздо более простым. Использование EUC-KR в веб-службах устарело. Вам лучше принять UTF-8 в ближайшее время.

+0

О, боже мой, ты такой гений. Большое вам спасибо за то, что вы потратили драгоценное время на решение моей проблемы. Это выглядит так сложно. Я бы никогда не разрешил это сам. Еще раз спасибо. Я знаю, что сервер действительно старый, но есть только способ использовать его для моего приложения. –