การใช้ DeepL Translator ด้วย Python (ตอนที่ 2)

ในบทความนี้ เราจะมาแนะนำวิธีการใช้งาน API ของ DeepL ในตอนที่ 2 ซึ่งเป็นเรื่องเกี่ยวกับการแปลไฟล์ (สามารถดูตอนที่ 1 ได้ ที่นี่)
※บทความนี้ตั้งอยู่บนพื้นฐานความรู้เบื้องต้นเกี่ยวกับ Python และ Linux

การแปลไฟล์ข้อความ

หลังจากวอร์มอัพกันเสร็จแล้ว ต่อไปเรามาลองแปลไฟล์กันดูครับ
การแปลไฟล์จำเป็นต้องใช้การเรียก API ร่วมกัน 3 ขั้นตอน
ให้เตรียมไฟล์ข้อความที่มีภาษาญี่ปุ่นอยู่ข้างในชื่อ test.txt ไว้
เราจะมาสร้างกลไกเพื่อแปลไฟล์นั้นเป็นภาษาอังกฤษ (สหรัฐอเมริกา) และบันทึกเป็น test.trans.txt

ขั้นตอนที่ 1: การอัปโหลดไฟล์ภาษาต้นฉบับ

เมื่อส่งคำขอแปลไปยังเซิร์ฟเวอร์ของ DeepL ให้ระบุไฟล์ต้นฉบับ

$ curl https://api.deepl.com/v2/document \
$ -F file=@test.txt \
$ -F auth_key=${auth_key} \
$ -F target_lang=en-us

 

document_id และ document_key ของไฟล์ที่ได้รับคำขอแปลแล้ว
จะถูกส่งกลับมาจากเซิร์ฟเวอร์ในรูปแบบ JSON เช่นเคย
โค้ด Python สำหรับการประมวลผลจนถึงขั้นตอนการส่งมีดังนี้:

url = 'https://api.deepl.com/v2/document'
files = dict()
files['file'] = open(fn, 'rb')
files['auth_key'] = (None, get_key())
files['target_lang'] = (None, 'en-us')
res = requests.post(url, files=files)

 

การระบุ auth_key และ target_lang นั้นค่อนข้างซับซ้อนเล็กน้อย
วิธีการระบุรายการใน files นั้นมีหลายวิธี หากใช้ tuple 2 รายการ
รายการแรกคือชื่อไฟล์ และรายการที่สองคือออบเจกต์
หากต้องการระบุเป็นสตริง จะต้องเขียนในลักษณะนี้
อีกวิธีหนึ่งคือการเก็บ auth_key และ target_lang ไว้ใน data (รูปแบบ dict)
เช่นเดียวกับการแปลสตริงในตอนแรก
แล้วส่งทั้ง data และ files ไปยัง requests.post() พร้อมกัน

ขั้นตอนที่ 2: การรับสถานะกระบวนการแปล

ตรวจสอบสถานะการแปลของไฟล์ที่กำลังดำเนินการอยู่:

$ document_id=[documentID]
$ document_key=[documentKey]
$ curl https://api.deepl.com/v2/document/${document_id} \
$ -d auth_key=${auth_key} \
$ -d document_key=${document_key}

 

สถานะมี 4 แบบ ได้แก่ queued (รับคำขอแล้ว), translating (กำลังแปล),
error (เกิดข้อผิดพลาดในการแปล), และ done (แปลเสร็จสิ้น)
ในกรณีที่เป็น translating ระบบจะส่งค่าประมาณเวลาที่เหลือในการประมวลผลกลับมาด้วย
สมมติว่าได้กำหนดค่าตัวแปร document_id และ document_key เรียบร้อยแล้ว
โค้ด Python สำหรับการประมวลผลจนถึงขั้นตอนการส่งมีดังนี้:

url = f'https://api.deepl.com/v2/document/{document_id}'
data = dict()
data['auth_key'] = get_key()
data['document_key'] = document_key
res = requests.post(url, data=data)

 

ขั้นตอนที่ 3: การดาวน์โหลดไฟล์ภาษาปลายทาง

เมื่อสถานะการแปลเป็น done แล้ว ให้ดาวน์โหลดไฟล์:

$ curl https://api.deepl.com/v2/document/${document_id}/result \
$ -d auth_key=${auth_key} \
$ -d document_key=${document_key} > test.trans.txt

 

ดาวน์โหลดได้เพียงครั้งเดียวเท่านั้น
ผลลัพธ์การแปลจะถูกเปลี่ยนเส้นทาง (บันทึก) ไปยัง test.trans.txt
กระบวนการจนถึงขั้นตอนการส่งข้อมูลเมื่อเขียนด้วย Python จะเป็นดังนี้:

url = f'https://api.deepl.com/v2/document/{document_id}/result'
data = dict()
data['auth_key'] = get_key()
data['document_key'] = document_key
res = requests.post(url, data=data)

 

กระบวนการแปลไฟล์

สุดท้ายนี้ เราจะเชื่อมโยงกระบวนการทั้งหมดเข้าด้วยกัน
เนื่องจากขั้นตอนที่ 2 จะส่งกลับมาเพียงสถานะความคืบหน้าของการแปลเท่านั้น
จึงจำเป็นต้องมีกระบวนการรอเพื่อรับผลลัพธ์ดังกล่าว โดยพื้นฐานแล้ว:
・หากเป็น translating ให้รอ (sleep) ตามจำนวนวินาทีที่เหลืออยู่ใน seconds_remaining
แล้วตรวจสอบสถานะความคืบหน้าอีกครั้ง
・หากเป็น done หรือ error ให้หลุดออกจากลูป
กระบวนการข้างต้นเมื่อเขียนด้วย Python จะเป็นดังนี้:

import requests
import json
from time import sleep

def get_key():
return open('key.txt').read().rstrip()

def upload_src(fn):
'''
ขั้นตอนการแปลไฟล์ 1: อัปโหลดไฟล์ภาษาต้นฉบับ
'''
url = 'https://api.deepl.com/v2/document'
files = dict()
files['file'] = open(fn, 'rb')
files['auth_key'] = (None, get_key())
files['target_lang'] = (None, 'en-us')

res = requests.post(url, files=files)
res_status = res.status_code # หากสำเร็จจะเป็น 200 (ยังไม่ได้ใช้ในตอนนี้)
res_text = res.text
res_data = json.loads(res_text)
document_id = res_data['document_id']
document_key = res_data['document_key']
return document_id, document_key

def get_trans_status(document_id, document_key):
'''
ขั้นตอนย่อยของขั้นตอนที่ 2: ดึงสถานะการประมวลผลการแปล
'''
url = f'https://api.deepl.com/v2/document/{document_id}'
data = dict()
data['auth_key'] = get_key()
data['document_key'] = document_key

res = requests.post(url, data=data)
res_status = res.status_code # หากสำเร็จจะเป็น 200 (ยังไม่ได้ใช้ในตอนนี้)
res_text = res.text
res_data = json.loads(res_text)
return res_data

def check_proceeding(document_id, document_key):
    ”’
    ขั้นตอนการแปลไฟล์ที่ 2: รอการประมวลผลการแปล
    ”’
    while True:
        res = get_trans_status(document_id, document_key)
        status = res[‘status’]
        print(f’status: {status}’, flush=True)
        seconds_remaining = 0
        if status == ‘done’ or status == ‘error’:
            break
        elif status == ‘translating’:
            if ‘seconds_remaining’ in res:
                seconds_remaining = int(res[‘seconds_remaining’])
                # ป้องกันข้อผิดพลาด
                if seconds_remaining <= 0:
                    seconds_remaining = 10
        else: # เช่น queued
            pass
        print(f’…waiting for (another) {seconds_remaining}s’, flush=True)
        sleep(seconds_remaining)
    return status

def download_tgt(fn, document_id, document_key):
    ”’
    ขั้นตอนการแปลไฟล์ที่ 3: ดาวน์โหลดไฟล์ภาษาปลายทาง
    ”’
    url = f’https://api.deepl.com/v2/document/{document_id}/result’
    data = dict()
    data[‘auth_key’] = get_key()
    data[‘document_key’] = document_key

    res = requests.post(url, data=data)
    res_status = res.status_code # 200 หากสำเร็จ (ยังไม่ได้ใช้ในขณะนี้)
    tgt_bin = res._content
    with open(fn, ‘w’, encoding=’utf-8′) as f:
        print(tgt_bin.decode(‘utf-8’), end=”, file=f)

def main():
    fn_src = ‘test.txt’
    fn_tgt = fn_src.replace(‘.txt’, ‘.trans.txt’)

    print(f’fn_src: {fn_src}’)
    print(f’fn_tgt: {fn_tgt}’)

print(f'uploading: {fn_src}')
document_id, document_key = upload_src(fn_src)
status = check_proceeding(document_id, document_key)
if status == 'done':
print(f'downloading: {fn_tgt}')
download_tgt(fn_tgt, document_id, document_key)

if __name__ == '__main__':
main()

 

การเรียกใช้ API ทั้ง 3 ประเภทมีกระบวนการที่คล้ายคลึงกัน แต่เพื่อจุดประสงค์ในหัวข้อ "การเขียนคำสั่ง curl ด้วย Python"
จึงจงใจเขียนแบบยืดเยื้อโดยไม่รวมเข้าด้วยกัน

สรุปแล้ว ในบทความนี้:

・แปลไฟล์โดยใช้ API ของ DeepL
・สร้างโปรแกรมโดยแปลงเนื้อหาของคำสั่ง curl ให้เป็น Python

ขอบคุณที่อ่านจนจบ