การใช้ BigQuery กับ Python

1. ภาพรวม

BigQuery คือคลังข้อมูลการวิเคราะห์ที่มีการจัดการอย่างเต็มรูปแบบ มีความจุระดับเพทาไบต์ และมีต้นทุนต่ำของ Google BigQuery เป็น NoOps ซึ่งไม่มีโครงสร้างพื้นฐานที่ต้องจัดการและคุณไม่จำเป็นต้องมีผู้ดูแลฐานข้อมูล คุณจึงมุ่งเน้นที่การวิเคราะห์ข้อมูลเพื่อค้นหาข้อมูลเชิงลึกที่มีความหมาย ใช้ SQL ที่คุ้นเคย และใช้ประโยชน์จากโมเดลการชำระเงินตามการใช้งาน

ในโค้ดแล็บนี้ คุณจะได้ใช้ไลบรารีของไคลเอ็นต์ Google Cloud สำหรับ Python เพื่อค้นหาชุดข้อมูลสาธารณะของ BigQuery ด้วย Python

สิ่งที่คุณจะได้เรียนรู้

  • วิธีใช้ Cloud Shell
  • วิธีเปิดใช้ BigQuery API
  • วิธีตรวจสอบสิทธิ์คำขอ API
  • วิธีติดตั้งไลบรารีของไคลเอ็นต์ Python
  • วิธีค้นหาผลงานของเชกสเปียร์
  • วิธีค้นหาชุดข้อมูล GitHub
  • วิธีปรับสถิติการแคชและการแสดงผล

สิ่งที่คุณต้องมี

  • โปรเจ็กต์ Google Cloud
  • เบราว์เซอร์ เช่น Chrome หรือ Firefox
  • คุ้นเคยกับการใช้ Python

แบบสำรวจ

คุณจะใช้บทแนะนำนี้อย่างไร

อ่านอย่างเดียว อ่านและทำแบบฝึกหัด

คุณจะให้คะแนนประสบการณ์การใช้งาน Python เท่าใด

ผู้ฝึกหัด ขั้นกลาง ผู้ชำนาญ

คุณจะให้คะแนนประสบการณ์การใช้บริการ Google Cloud เท่าใด

ผู้ฝึกหัด ขั้นกลาง ผู้ชำนาญ

2. การตั้งค่าและข้อกำหนด

การตั้งค่าสภาพแวดล้อมแบบเรียนรู้ด้วยตนเอง

  1. ลงชื่อเข้าใช้ Google Cloud Console แล้วสร้างโปรเจ็กต์ใหม่หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ หากยังไม่มีบัญชี Gmail หรือ Google Workspace คุณต้องสร้างบัญชี

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • ชื่อโปรเจ็กต์คือชื่อที่แสดงสำหรับผู้เข้าร่วมโปรเจ็กต์นี้ โดยเป็นสตริงอักขระที่ Google APIs ไม่ได้ใช้ และคุณสามารถอัปเดตได้ทุกเมื่อ
  • รหัสโปรเจ็กต์ต้องไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมดและเปลี่ยนแปลงไม่ได้ (เปลี่ยนไม่ได้หลังจากตั้งค่าแล้ว) Cloud Console จะสร้างสตริงที่ไม่ซ้ำกันโดยอัตโนมัติ ซึ่งโดยปกติแล้วคุณไม่จำเป็นต้องสนใจว่าสตริงนั้นคืออะไร ใน Codelab ส่วนใหญ่ คุณจะต้องอ้างอิงรหัสโปรเจ็กต์ (และโดยทั่วไปจะระบุเป็น PROJECT_ID) ดังนั้นหากไม่ชอบรหัสที่สร้างขึ้น ให้สร้างรหัสแบบสุ่มอีกรหัส หรือจะลองใช้รหัสของคุณเองและดูว่ามีรหัสนั้นหรือไม่ก็ได้ จากนั้นจะ "หยุด" หลังจากสร้างโปรเจ็กต์แล้ว
  • นอกจากนี้ยังมีค่าที่ 3 คือหมายเลขโปรเจ็กต์ ซึ่ง API บางตัวใช้ ดูข้อมูลเพิ่มเติมเกี่ยวกับค่าทั้ง 3 นี้ได้ในเอกสารประกอบ
  1. จากนั้นคุณจะต้องเปิดใช้การเรียกเก็บเงินใน Cloud Console เพื่อใช้ทรัพยากร/API ของ Cloud การทำตาม Codelab นี้ไม่ควรมีค่าใช้จ่ายมากนัก หรืออาจไม่มีเลย หากต้องการปิดแหล่งข้อมูลเพื่อไม่ให้มีการเรียกเก็บเงินนอกเหนือจากบทแนะนำนี้ ให้ทำตามวิธีการ "ล้างข้อมูล" ที่ตอนท้ายของ Codelab ผู้ใช้ Google Cloud รายใหม่มีสิทธิ์เข้าร่วมโปรแกรมช่วงทดลองใช้ฟรีมูลค่า$300 USD

เริ่มต้น Cloud Shell

แม้ว่าคุณจะใช้งาน Google Cloud จากระยะไกลจากแล็ปท็อปได้ แต่ใน Codelab นี้คุณจะใช้ Google Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานในระบบคลาวด์

เปิดใช้งาน Cloud Shell

  1. จาก Cloud Console ให้คลิกเปิดใช้งาน Cloud Shell 853e55310c205094.png

55efc1aaa7a4d3ad.png

หากไม่เคยเริ่มใช้ Cloud Shell มาก่อน คุณจะเห็นหน้าจอระดับกลาง (ด้านล่าง) ที่อธิบายว่า Cloud Shell คืออะไร ในกรณีนี้ ให้คลิกต่อไป (และคุณจะไม่เห็นหน้าจอนี้อีก) หน้าจอแบบครั้งเดียวจะมีลักษณะดังนี้

9c92662c6a846a5c.png

การจัดสรรและเชื่อมต่อกับ Cloud Shell จะใช้เวลาไม่นาน

9f0e51b578fecce5.png

เครื่องเสมือนนี้มีเครื่องมือพัฒนาซอฟต์แวร์ทั้งหมดที่คุณต้องการ โดยมีไดเรกทอรีหลักแบบถาวรขนาด 5 GB และทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก คุณสามารถทำงานในโค้ดแล็บนี้ได้โดยใช้เพียงเบราว์เซอร์หรือ Chromebook

เมื่อเชื่อมต่อกับ Cloud Shell แล้ว คุณควรเห็นว่าคุณได้รับการตรวจสอบสิทธิ์แล้วและโปรเจ็กต์ได้รับการตั้งค่าเป็นรหัสโปรเจ็กต์ของคุณแล้ว

  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคุณได้รับการตรวจสอบสิทธิ์แล้ว
gcloud auth list

เอาต์พุตของคำสั่ง

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อยืนยันว่าคำสั่ง gcloud รู้จักโปรเจ็กต์ของคุณ
gcloud config list project

เอาต์พุตของคำสั่ง

[core]
project = <PROJECT_ID>

หากไม่ได้ตั้งค่าไว้ คุณตั้งค่าได้ด้วยคำสั่งนี้

gcloud config set project <PROJECT_ID>

เอาต์พุตของคำสั่ง

Updated property [core/project].

3. เปิดใช้ API

ควรเปิดใช้ BigQuery API โดยค่าเริ่มต้นในโปรเจ็กต์ Google Cloud ทั้งหมด คุณตรวจสอบได้ว่าข้อความนี้เป็นจริงหรือไม่ด้วยคำสั่งต่อไปนี้ใน Cloud Shell คุณควรเห็น BigQuery แสดงอยู่

gcloud services list

คุณควรเห็น BigQuery แสดงอยู่

NAME                              TITLE
bigquery.googleapis.com           BigQuery API

...

ในกรณีที่ไม่ได้เปิดใช้ BigQuery API คุณสามารถใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อเปิดใช้

gcloud services enable bigquery.googleapis.com

4. ตรวจสอบสิทธิ์คำขอ API

หากต้องการส่งคำขอไปยัง BigQuery API คุณต้องใช้บัญชีบริการ บัญชีบริการเป็นของโปรเจ็กต์ของคุณ และไลบรารีของไคลเอ็นต์ Python ของ Google Cloud จะใช้บัญชีนี้เพื่อส่งคำขอ BigQuery API บัญชีบริการจะแสดงด้วยอีเมลเช่นเดียวกับบัญชีผู้ใช้อื่นๆ ในส่วนนี้ คุณจะใช้ Cloud SDK เพื่อสร้างบัญชีบริการ จากนั้นสร้างข้อมูลเข้าสู่ระบบที่คุณจะต้องใช้เพื่อตรวจสอบสิทธิ์ในฐานะบัญชีบริการ

ก่อนอื่น ให้ตั้งค่าตัวแปรสภาพแวดล้อม PROJECT_ID ดังนี้

export PROJECT_ID=$(gcloud config get-value core/project)

จากนั้นสร้างบัญชีบริการใหม่เพื่อเข้าถึง BigQuery API โดยใช้ข้อมูลต่อไปนี้

gcloud iam service-accounts create my-bigquery-sa \
  --display-name "my bigquery service account"

จากนั้นสร้างข้อมูลเข้าสู่ระบบที่โค้ด Python จะใช้เพื่อเข้าสู่ระบบในฐานะบัญชีบริการใหม่ สร้างข้อมูลเข้าสู่ระบบเหล่านี้และบันทึกเป็นไฟล์ JSON ~/key.json โดยใช้คำสั่งต่อไปนี้

gcloud iam service-accounts keys create ~/key.json \
  --iam-account my-bigquery-sa@${PROJECT_ID}.iam.gserviceaccount.com

สุดท้าย ให้ตั้งค่าGOOGLE_APPLICATION_CREDENTIALSตัวแปรสภาพแวดล้อม ซึ่งไลบรารีของไคลเอ็นต์ Python สำหรับ BigQuery จะใช้ตัวแปรนี้ (อธิบายไว้ในขั้นตอนถัดไป) เพื่อค้นหาข้อมูลเข้าสู่ระบบ ควรตั้งค่าตัวแปรสภาพแวดล้อมเป็นเส้นทางแบบเต็มของไฟล์ JSON ข้อมูลเข้าสู่ระบบที่คุณสร้างขึ้นโดยใช้คำสั่งต่อไปนี้

export GOOGLE_APPLICATION_CREDENTIALS=~/key.json

คุณอ่านข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบสิทธิ์ BigQuery API ได้

5. ตั้งค่าการควบคุมการเข้าถึง

BigQuery ใช้ Identity and Access Management (IAM) เพื่อจัดการการเข้าถึงทรัพยากร BigQuery มีบทบาทที่กำหนดไว้ล่วงหน้าหลายบทบาท (ผู้ใช้, dataOwner, dataViewer ฯลฯ) ที่คุณสามารถกำหนดให้กับบัญชีบริการที่สร้างในขั้นตอนก่อนหน้า ดูข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมการเข้าถึงได้ในเอกสารประกอบของ BigQuery

ก่อนที่จะค้นหาชุดข้อมูลสาธารณะได้ คุณต้องตรวจสอบว่าบัญชีบริการมีบทบาทroles/bigquery.userอย่างน้อย ใน Cloud Shell ให้เรียกใช้คำสั่งต่อไปนี้เพื่อกำหนดบทบาทผู้ใช้ให้กับบัญชีบริการ

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member "serviceAccount:my-bigquery-sa@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role "roles/bigquery.user"

คุณเรียกใช้คำสั่งต่อไปนี้เพื่อยืนยันว่าบัญชีบริการมีบทบาทผู้ใช้ได้

gcloud projects get-iam-policy $PROJECT_ID

คุณควรเห็นสิ่งต่อไปนี้

bindings:
- members:
  - serviceAccount:my-bigquery-sa@<PROJECT_ID>.iam.gserviceaccount.com
  role: roles/bigquery.user
...

6. ติดตั้งไลบรารีของไคลเอ็นต์

ติดตั้งไลบรารีของไคลเอ็นต์ Python สำหรับ BigQuery โดยทำดังนี้

pip3 install --user --upgrade google-cloud-bigquery

ตอนนี้คุณก็พร้อมที่จะเขียนโค้ดด้วย BigQuery API แล้ว

7. ค้นหางานของเชกสเปียร์

ชุดข้อมูลสาธารณะคือชุดข้อมูลที่จัดเก็บไว้ใน BigQuery และพร้อมให้บริการแก่บุคคลทั่วไป นอกจากนี้ยังมีชุดข้อมูลสาธารณะอื่นๆ อีกมากมายที่คุณสามารถค้นหาได้ แม้ว่า Google จะโฮสต์ชุดข้อมูลบางชุด แต่ชุดข้อมูลส่วนใหญ่โฮสต์โดยบุคคลที่สาม ดูข้อมูลเพิ่มเติมได้ที่หน้าชุดข้อมูลสาธารณะ

นอกจากชุดข้อมูลสาธารณะแล้ว BigQuery ยังมีตารางตัวอย่างจำนวนจำกัดที่คุณค้นหาได้ ตารางเหล่านี้อยู่ในชุดข้อมูล bigquery-public-data:samples ตาราง shakespeare ในชุดข้อมูล samples มีดัชนีคำของผลงานของเชกสเปียร์ โดยจะแสดงจำนวนครั้งที่คำแต่ละคำปรากฏในแต่ละคลัง

ในขั้นตอนนี้ คุณจะค้นหาตาราง shakespeare

ก่อนอื่น ให้สร้างแอปพลิเคชัน Python อย่างง่ายใน Cloud Shell ซึ่งคุณจะใช้เพื่อเรียกใช้ตัวอย่าง Translation API

mkdir bigquery-demo
cd bigquery-demo
touch app.py

เปิดเครื่องมือแก้ไขโค้ดจากด้านขวาบนของ Cloud Shell โดยทำดังนี้

b648141af44811a3.png

ไปที่ไฟล์ app.py ในโฟลเดอร์ bigquery-demo แล้วแทนที่โค้ดด้วยโค้ดต่อไปนี้

from google.cloud import bigquery

client = bigquery.Client()

query = """
    SELECT corpus AS title, COUNT(word) AS unique_words
    FROM `bigquery-public-data.samples.shakespeare`
    GROUP BY title
    ORDER BY unique_words
    DESC LIMIT 10
"""
results = client.query(query)

for row in results:
    title = row['title']
    unique_words = row['unique_words']
    print(f'{title:<20} | {unique_words}')

ใช้เวลาสักครู่เพื่อศึกษาโค้ดและดูวิธีค้นหาตาราง

กลับไปที่ Cloud Shell แล้วเรียกใช้แอปโดยทำดังนี้

python3 app.py

คุณจะเห็นรายการคำและจำนวนครั้งที่คำนั้นๆ ปรากฏ ดังนี้

hamlet               | 5318
kinghenryv           | 5104
cymbeline            | 4875
troilusandcressida   | 4795
kinglear             | 4784
kingrichardiii       | 4713
2kinghenryvi         | 4683
coriolanus           | 4653
2kinghenryiv         | 4605
antonyandcleopatra   | 4582

8. ค้นหาชุดข้อมูล GitHub

ตอนนี้คุณจะออกการค้นหากับชุดข้อมูลสาธารณะของ GitHub เพื่อทำความคุ้นเคยกับ BigQuery มากขึ้น คุณจะเห็นข้อความคอมมิตที่พบบ่อยที่สุดใน GitHub นอกจากนี้ คุณยังใช้เว็บคอนโซลของ BigQuery เพื่อแสดงตัวอย่างและเรียกใช้การค้นหาเฉพาะกิจได้ด้วย

หากต้องการดูว่าข้อมูลมีลักษณะอย่างไร ให้เปิดชุดข้อมูล GitHub ในเว็บ UI ของ BigQuery โดยทำดังนี้

เปิดgithub_reposตาราง

คลิกปุ่มแสดงตัวอย่างเพื่อดูว่าข้อมูลมีลักษณะอย่างไร

d3f0dc7400fbe678.png

ไปที่ไฟล์ app.py ในโฟลเดอร์ bigquery_demo แล้วแทนที่โค้ดด้วยโค้ดต่อไปนี้

from google.cloud import bigquery

client = bigquery.Client()

query = """
    SELECT subject AS subject, COUNT(*) AS num_duplicates
    FROM bigquery-public-data.github_repos.commits
    GROUP BY subject
    ORDER BY num_duplicates
    DESC LIMIT 10
"""
results = client.query(query)

for row in results:
    subject = row['subject']
    num_duplicates = row['num_duplicates']
    print(f'{subject:<20} | {num_duplicates:>9,}')

โปรดใช้เวลาสักครู่เพื่อศึกษาโค้ดและดูวิธีค้นหาข้อความคอมมิตที่พบบ่อยที่สุดในตาราง

กลับไปที่ Cloud Shell แล้วเรียกใช้แอปโดยทำดังนี้

python3 app.py

คุณควรเห็นรายการข้อความคอมมิตและเหตุการณ์ที่เกิดขึ้นดังนี้

Update README.md     | 1,685,515
Initial commit       | 1,577,543
update               |   211,017
                     |   155,280
Create README.md     |   153,711
Add files via upload |   152,354
initial commit       |   145,224
first commit         |   110,314
Update index.html    |    91,893
Update README        |    88,862

9. การแคชและสถิติ

BigQuery จะแคชผลลัพธ์ของการค้นหา ด้วยเหตุนี้ การค้นหาครั้งต่อๆ ไปจึงใช้เวลาน้อยลง คุณปิดใช้การแคชได้ด้วยตัวเลือกการค้นหา นอกจากนี้ BigQuery ยังติดตามสถิติเกี่ยวกับการค้นหา เช่น เวลาที่สร้าง เวลาสิ้นสุด และจำนวนไบต์ทั้งหมดที่ประมวลผล

ในขั้นตอนนี้ คุณจะปิดใช้การแคชและแสดงสถิติเกี่ยวกับคำค้นหาด้วย

ไปที่ไฟล์ app.py ในโฟลเดอร์ bigquery_demo แล้วแทนที่โค้ดด้วยโค้ดต่อไปนี้

from google.cloud import bigquery

client = bigquery.Client()

query = """
    SELECT subject AS subject, COUNT(*) AS num_duplicates
    FROM bigquery-public-data.github_repos.commits
    GROUP BY subject
    ORDER BY num_duplicates
    DESC LIMIT 10
"""
job_config = bigquery.job.QueryJobConfig(use_query_cache=False)
results = client.query(query, job_config=job_config)

for row in results:
    subject = row['subject']
    num_duplicates = row['num_duplicates']
    print(f'{subject:<20} | {num_duplicates:>9,}')

print('-'*60)
print(f'Created: {results.created}')
print(f'Ended:   {results.ended}')
print(f'Bytes:   {results.total_bytes_processed:,}')

ข้อควรทราบเกี่ยวกับโค้ดมีดังนี้ ก่อนอื่น ให้ปิดใช้การแคชโดยการเพิ่ม QueryJobConfig และตั้งค่า use_query_cache เป็น false ประการที่ 2 คุณเข้าถึงสถิติเกี่ยวกับคำค้นหาจากออบเจ็กต์งาน

กลับไปที่ Cloud Shell แล้วเรียกใช้แอปโดยทำดังนี้

python3 app.py

คุณควรเห็นรายการข้อความคอมมิตและจำนวนครั้งที่ข้อความนั้นปรากฏเช่นเดียวกับก่อนหน้านี้ นอกจากนี้ คุณควรเห็นสถิติบางอย่างเกี่ยวกับการค้นหาที่ส่วนท้ายด้วย

Update README.md     | 1,685,515
Initial commit       | 1,577,543
update               |   211,017
                     |   155,280
Create README.md     |   153,711
Add files via upload |   152,354
initial commit       |   145,224
first commit         |   110,314
Update index.html    |    91,893
Update README        |    88,862
------------------------------------------------------------
Created: 2020-04-03 13:30:08.801000+00:00
Ended:   2020-04-03 13:30:15.334000+00:00
Bytes:   2,868,251,894

10. การโหลดข้อมูลลงใน BigQuery

หากต้องการค้นหาข้อมูลของคุณเอง คุณต้องโหลดข้อมูลลงใน BigQuery BigQuery รองรับการโหลดข้อมูลจากหลายแหล่งที่มา ซึ่งรวมถึง Cloud Storage, บริการอื่นๆ ของ Google และแหล่งที่มาอื่นๆ ที่อ่านได้ คุณยังสตรีมข้อมูลได้โดยใช้การแทรกแบบสตรีม ดูข้อมูลเพิ่มเติมได้ที่หน้าการโหลดข้อมูลลงใน BigQuery

ในขั้นตอนนี้ คุณจะโหลดไฟล์ JSON ที่จัดเก็บไว้ใน Cloud Storage ลงในตาราง BigQuery ไฟล์ JSON อยู่ที่ gs://cloud-samples-data/bigquery/us-states/us-states.json

หากต้องการทราบเนื้อหาของไฟล์ JSON คุณสามารถใช้gsutilเครื่องมือบรรทัดคำสั่งเพื่อดาวน์โหลดไฟล์ใน Cloud Shell ได้โดยทำดังนี้

gsutil cp gs://cloud-samples-data/bigquery/us-states/us-states.json .

คุณจะเห็นว่ามีรายการรัฐในสหรัฐอเมริกา และแต่ละรัฐเป็นเอกสาร JSON ในบรรทัดแยกกัน

head us-states.json
{"name": "Alabama", "post_abbr": "AL"}
{"name": "Alaska", "post_abbr":  "AK"}
...

หากต้องการโหลดไฟล์ JSON นี้ลงใน BigQuery ให้ไปที่app.pyไฟล์ภายในโฟลเดอร์bigquery_demo แล้วแทนที่โค้ดด้วยโค้ดต่อไปนี้

from google.cloud import bigquery

client = bigquery.Client()

gcs_uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.json'

dataset = client.create_dataset('us_states_dataset')
table = dataset.table('us_states_table')

job_config = bigquery.job.LoadJobConfig()
job_config.schema = [
    bigquery.SchemaField('name', 'STRING'),
    bigquery.SchemaField('post_abbr', 'STRING'),
]
job_config.source_format = bigquery.SourceFormat.NEWLINE_DELIMITED_JSON

load_job = client.load_table_from_uri(gcs_uri, table, job_config=job_config)

print('JSON file loaded to BigQuery')

ใช้เวลาสักครู่เพื่อศึกษาว่าโค้ดโหลดไฟล์ JSON และสร้างตารางที่มีสคีมาภายใต้ชุดข้อมูลอย่างไร

กลับไปที่ Cloud Shell แล้วเรียกใช้แอปโดยทำดังนี้

python3 app.py

ระบบจะสร้างชุดข้อมูลและตารางใน BigQuery

หากต้องการยืนยันว่าสร้างชุดข้อมูลแล้ว ให้ไปที่คอนโซล BigQuery คุณควรเห็นชุดข้อมูลและตารางใหม่ เปลี่ยนไปที่แท็บตัวอย่างของตารางเพื่อดูข้อมูล

8c7d2621820a5ac4.png

11. ยินดีด้วย

คุณได้เรียนรู้วิธีใช้ BigQuery กับ Python แล้ว

ล้างข้อมูล

โปรดดำเนินการดังนี้เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud สำหรับทรัพยากรที่ใช้ในบทแนะนำนี้

  • ใน Cloud Console ให้ไปที่หน้าจัดการทรัพยากร
  • เลือกโปรเจ็กต์ในรายการโปรเจ็กต์ แล้วคลิกลบ
  • ในกล่องโต้ตอบ ให้พิมพ์รหัสโปรเจ็กต์ แล้วคลิกปิดเพื่อลบโปรเจ็กต์

ดูข้อมูลเพิ่มเติม

ใบอนุญาต

ผลงานนี้ได้รับอนุญาตภายใต้สัญญาอนุญาตครีเอทีฟคอมมอนส์สำหรับยอมรับสิทธิของผู้สร้าง (Creative Commons Attribution License) 2.0 แบบทั่วไป