Python Pandas Error tokenizing data


343

Saya mencoba menggunakan panda untuk memanipulasi file .csv tapi saya mendapatkan kesalahan ini:

pandas.parser.CParserError: Kesalahan tokenizing data. C error: Diharapkan 2 bidang pada baris 3, lihat 12

Saya telah mencoba membaca panda docs, tetapi tidak menemukan apa pun.

Kode saya sederhana:

path = 'GOOG Key Ratios.csv'
#print(open(path).read())
data = pd.read_csv(path)

Bagaimana saya bisa menyelesaikan ini? Haruskah saya menggunakan csvmodul atau bahasa lain?

File dari Morningstar


10
Jika kesalahan ini muncul saat membaca file yang ditulis oleh pandas.to_csv(), itu MUNGKIN karena ada '\ r' dalam nama kolom, dalam hal ini to_csv () akan benar-benar menulis nama kolom berikutnya ke dalam kolom pertama dari frame data, menyebabkan perbedaan antara jumlah kolom dalam baris X pertama. Perbedaan ini adalah salah satu penyebab kesalahan C.
user0

9
Kadang-kadang hanya secara eksplisit memberikan parameter "sep" membantu. Tampaknya menjadi masalah parser.
gilgamash

2
Kesalahan ini dapat muncul juga ketika Anda menggunakan koma sebagai pembatas dan Anda memiliki lebih banyak koma dari yang diharapkan (lebih banyak bidang di baris kesalahan kemudian didefinisikan dalam header). Jadi, Anda harus menghapus bidang tambahan atau menghapus koma tambahan jika ada karena kesalahan. Anda dapat memperbaiki ini secara manual dan kemudian Anda tidak perlu melewati garis kesalahan.
tsveti_iko

2
Komentar dari gilgamash membantu saya. Buka file csv dalam editor teks (seperti editor windows atau notepad ++) jadi lihat karakter mana yang digunakan untuk pemisahan. Jika itu adalah titik koma misalnya, coba pd.read_csv("<path>", sep=";"). Jangan gunakan Excel untuk memeriksa karena kadang-kadang menempatkan data ke dalam kolom secara default dan karenanya menghapus pemisah.
Julian

Mengenai komentar oleh @gilgamash - ini mengirim saya ke arah yang benar, namun dalam kasus saya itu diselesaikan dengan secara eksplisit tidak memberikan parameter "sep".
TheLoneDeranger

Jawaban:


515

Anda juga bisa mencoba;

data = pd.read_csv('file1.csv', error_bad_lines=False)

Harap perhatikan bahwa ini akan menyebabkan garis yang melanggar dilewati.


152
Perhatikan bahwa menggunakan error_bad_lines = Salah akan menyebabkan garis yang melanggar dilewati.
biobirdman

10
Tersandung pada jawaban ini, apakah ada cara untuk mengisi kolom yang hilang pada garis yang menghasilkan sesuatu seperti expected 8 fields, saw 9?
Petra Barus

26
Solusi yang lebih baik adalah menyelidiki file yang menyinggung dan untuk memperbaiki baris yang buruk sehingga mereka dapat dibaca oleh read_csv. @PetraBarus, mengapa tidak menambahkan kolom ke file CSV yang hilang (dengan nilai nol sesuai kebutuhan)?
dbliss

4
Ya, saya baru saja melakukannya. Jauh lebih mudah dengan menambahkan kolom. Membuka CSV dalam spreadsheet melakukan hal ini.
Petra Barus

5
Melewati names=["col1", "col2", ...]untuk jumlah maksimum kolom yang diharapkan juga berfungsi, dan ini adalah bagaimana saya memecahkan masalah ini ketika saya menemukannya. Lihat: stackoverflow.com/questions/18039057/...
Steven Rouk

100

Mungkin ada masalah dengan

  • pembatas dalam data Anda
  • baris pertama, seperti dicatat @TomAugspurger

Untuk mengatasinya, coba tentukan argumen sepdan / atau headersaat memanggil read_csv. Misalnya,

df = pandas.read_csv(fileName, sep='delimiter', header=None)

Dalam kode di atas, septentukan pembatas Anda dan header=Noneberi tahu panda bahwa data sumber Anda tidak memiliki baris untuk judul header / kolom. Demikian dikatakan oleh docs : "Jika file tidak mengandung baris header, maka Anda harus secara eksplisit meneruskan header = Tidak Ada". Dalam hal ini, panda secara otomatis membuat indeks bilangan bulat untuk setiap bidang {0,1,2, ...}.

Menurut dokumen, hal pembatas seharusnya tidak menjadi masalah. Dokumen mengatakan bahwa "jika sep adalah Tidak [tidak ditentukan], akan mencoba untuk secara otomatis menentukan ini." Namun saya belum beruntung dengan ini, termasuk contoh dengan pembatas yang jelas.


Ya, terkadang pembatas dapat menjadi penyebab masalah ini. Saya menghadapi masalah yang sama di mana pembatas adalah titik koma (;)
Anurag Sharma

43

Parser semakin bingung dengan header file. Bunyinya baris pertama dan menyimpulkan jumlah kolom dari baris itu. Tetapi dua baris pertama tidak mewakili data aktual dalam file.

Cobalah data = pd.read_csv(path, skiprows=2)


30

File CSV Anda mungkin memiliki jumlah kolom yang bervariasi dan read_csvmenyimpulkan jumlah kolom dari beberapa baris pertama. Dua cara untuk menyelesaikannya dalam kasus ini:

1) Ubah file CSV menjadi baris pertama dummy dengan jumlah kolom maksimum (dan tentukan header=[0])

2) Atau gunakan di names = list(range(0,N))mana N adalah jumlah maksimum kolom.


25

Ini jelas merupakan masalah pembatas, karena sebagian besar CSV csv dibuat menggunakan sep='/t'jadi cobalah untuk read_csvmenggunakan karakter tab (\t)menggunakan pemisah /t. jadi, coba buka menggunakan baris kode berikut.

data=pd.read_csv("File_path", sep='\t')

5
@MichaelQueue: Ini tidak benar. CSV, meskipun biasanya dibatasi oleh koma, dapat juga dibatasi oleh karakter lain. Lihat spesifikasi CSV . Mungkin berupa koma, tab ('\'), titik koma, dan mungkin spasi tambahan. :)
DJGrandpaJ

dalam kasus saya itu adalah masalah pemisah. read_csv rupanya default untuk koma, dan saya memiliki bidang teks yang menyertakan koma (dan data disimpan dengan pemisah yang berbeda pula)
user108569

Jika koma digunakan dalam nilai tetapi tab adalah pembatas dan sep tidak digunakan (atau seperti yang disarankan di atas pembatas apa pun yang diasumsikan terjadi dalam nilai-nilai) maka kesalahan ini akan muncul. Pastikan pembatas tidak muncul di nilai mana pun, beberapa baris tampaknya memiliki jumlah kolom yang salah
demongolem

Saya menggunakan excel 2016 saat membuat CSV, dan menggunakan sep = ';' bekerja untuk saya
Abdullah Said

18

Saya memiliki masalah ini juga, tetapi mungkin karena alasan yang berbeda. Saya memiliki beberapa tanda koma di CSV saya yang menambahkan kolom tambahan yang coba dibaca oleh panda. Menggunakan karya-karya berikut tetapi mengabaikan garis buruk:

data = pd.read_csv('file1.csv', error_bad_lines=False)

Jika Anda ingin menjaga garis hack yang jelek untuk menangani kesalahan adalah dengan melakukan sesuatu seperti berikut:

line     = []
expected = []
saw      = []     
cont     = True 

while cont == True:     
    try:
        data = pd.read_csv('file1.csv',skiprows=line)
        cont = False
    except Exception as e:    
        errortype = e.message.split('.')[0].strip()                                
        if errortype == 'Error tokenizing data':                        
           cerror      = e.message.split(':')[1].strip().replace(',','')
           nums        = [n for n in cerror.split(' ') if str.isdigit(n)]
           expected.append(int(nums[0]))
           saw.append(int(nums[2]))
           line.append(int(nums[1])-1)
         else:
           cerror      = 'Unknown'
           print 'Unknown Error - 222'

if line != []:
    # Handle the errors however you want

Saya melanjutkan untuk menulis skrip untuk memasukkan kembali baris ke dalam DataFrame karena baris yang buruk akan diberikan oleh variabel 'baris' dalam kode di atas. Ini semua bisa dihindari dengan hanya menggunakan pembaca csv. Semoga para pengembang panda dapat membuatnya lebih mudah untuk menghadapi situasi ini di masa depan.


14

Saya memiliki masalah ini, di mana saya mencoba membaca dalam CSV tanpa memberikan nama kolom.

df = pd.read_csv(filename, header=None)

Saya menentukan nama kolom dalam daftar sebelumnya dan kemudian meneruskannya names, dan segera menyelesaikannya. Jika Anda tidak menetapkan nama kolom, Anda bisa membuat nama placeholder sebanyak jumlah kolom maksimum yang mungkin ada dalam data Anda.

col_names = ["col1", "col2", "col3", ...]
df = pd.read_csv(filename, names=col_names)

1
Jawaban ini lebih baik karena baris tidak dihapus dibandingkan jika menggunakan error_bad_line = Salah. Selain itu, Anda dapat dengan mudah mengetahui garis mana yang merupakan masalah setelah membuat kerangka data dari solusi ini.
zipline86

Saya setuju dengan @ zipline86. Jawaban ini aman dan cerdas.
Monica Heddneck

11

Saya sendiri pernah mengalami masalah ini beberapa kali. Hampir setiap waktu, alasannya adalah karena file yang saya coba buka bukan CSV yang disimpan dengan benar. Dan dengan "benar", maksud saya setiap baris memiliki jumlah pemisah atau kolom yang sama.

Biasanya itu terjadi karena saya telah membuka CSV di Excel kemudian menyimpannya dengan tidak benar. Meskipun ekstensi file masih .csv, format CSV murni telah diubah.

File apa pun yang disimpan dengan panda to_csv akan diformat dengan benar dan seharusnya tidak memiliki masalah itu. Tetapi jika Anda membukanya dengan program lain, itu dapat mengubah struktur.

Semoga itu bisa membantu.


8

Saya menemukan masalah yang sama. Menggunakan pd.read_table()pada file sumber yang sama tampaknya berhasil. Saya tidak bisa melacak alasannya tetapi ini merupakan solusi yang berguna untuk kasus saya. Mungkin seseorang yang lebih berpengetahuan dapat menjelaskan mengapa itu berhasil.

Sunting: Saya menemukan bahwa kesalahan ini merayap ketika Anda memiliki beberapa teks di file Anda yang tidak memiliki format yang sama dengan data aktual. Ini biasanya informasi header atau footer (lebih dari satu baris, jadi skip_header tidak berfungsi) yang tidak akan dipisahkan dengan jumlah koma yang sama dengan data aktual Anda (saat menggunakan read_csv). Menggunakan read_table menggunakan tab sebagai pembatas yang dapat menghindari kesalahan pengguna saat ini tetapi memperkenalkan yang lain.

Saya biasanya menyiasati ini dengan membaca data tambahan ke dalam file kemudian menggunakan metode read_csv ().

Solusi yang tepat mungkin berbeda tergantung pada file Anda yang sebenarnya, tetapi pendekatan ini berhasil bagi saya dalam beberapa kasus


6

Berikut ini berfungsi untuk saya (saya memposting jawaban ini, karena saya secara khusus memiliki masalah ini di Notebook Kolaborasi Google):

df = pd.read_csv("/path/foo.csv", delimiter=';', skiprows=0, low_memory=False)

1
Saya mencoba masalah ketika tidak menetapkan |sebagai pembatas untuk .csv saya. Saya lebih suka mencoba pendekatan ini terlebih dahulu, daripada melewatkan garis, atau garis buruk.
ivanleoncz

Saya juga memiliki masalah yang sama, saya berasumsi "\ t" akan terdeteksi sebagai pembatas secara default. Ini bekerja ketika saya secara eksplisit mengatur pembatas ke "\ t".
Rahul Jha

5

Saya punya masalah yang sama ketika mencoba membaca tabel dengan batasan tab dengan spasi, koma, dan kutipan:

1115794 4218    "k__Bacteria", "p__Firmicutes", "c__Bacilli", "o__Bacillales", "f__Bacillaceae", ""
1144102 3180    "k__Bacteria", "p__Firmicutes", "c__Bacilli", "o__Bacillales", "f__Bacillaceae", "g__Bacillus", ""
368444  2328    "k__Bacteria", "p__Bacteroidetes", "c__Bacteroidia", "o__Bacteroidales", "f__Bacteroidaceae", "g__Bacteroides", ""



import pandas as pd
# Same error for read_table
counts = pd.read_csv(path_counts, sep='\t', index_col=2, header=None, engine = 'c')

pandas.io.common.CParserError: Error tokenizing data. C error: out of memory

Ini mengatakan ada hubungannya dengan mesin parsing C (yang merupakan default). Mungkin mengubah ke python satu akan mengubah apa pun

counts = pd.read_table(path_counts, sep='\t', index_col=2, header=None, engine='python')

Segmentation fault (core dumped)

Nah, itu kesalahan yang berbeda.
Jika kita teruskan dan mencoba untuk menghapus spasi dari tabel, kesalahan dari mesin python berubah sekali lagi:

1115794 4218    "k__Bacteria","p__Firmicutes","c__Bacilli","o__Bacillales","f__Bacillaceae",""
1144102 3180    "k__Bacteria","p__Firmicutes","c__Bacilli","o__Bacillales","f__Bacillaceae","g__Bacillus",""
368444  2328    "k__Bacteria","p__Bacteroidetes","c__Bacteroidia","o__Bacteroidales","f__Bacteroidaceae","g__Bacteroides",""


_csv.Error: '   ' expected after '"'

Dan menjadi jelas bahwa panda mengalami masalah dalam menguraikan baris kami. Untuk mengurai tabel dengan mesin python saya perlu menghapus semua spasi dan kutipan dari tabel sebelumnya. Sementara itu C-engine terus menabrak bahkan dengan koma di baris.

Untuk menghindari membuat file baru dengan penggantian saya melakukan ini, karena tabel saya kecil:

from io import StringIO
with open(path_counts) as f:
    input = StringIO(f.read().replace('", ""', '').replace('"', '').replace(', ', ',').replace('\0',''))
    counts = pd.read_table(input, sep='\t', index_col=2, header=None, engine='python')

tl; dr
Ubah mesin parsing, cobalah untuk menghindari tanda kutip / koma / spasi yang tidak membatasi dalam data Anda.


5

Dataset yang saya gunakan memiliki banyak tanda kutip (") yang digunakan di luar format. Saya dapat memperbaiki kesalahan dengan memasukkan parameter ini untuk read_csv():

quoting=3 # 3 correlates to csv.QUOTE_NONE for pandas

2
menemukan hal yang sama persis. Sejauh yang saya ketahui, ini adalah jawaban yang benar. Yang diterima hanya menyembunyikan kesalahan.
lhk

Jawaban yang benar untuk saya juga. +1
Taha Jirjees

4

Gunakan pembatas dalam parameter

pd.read_csv(filename, delimiter=",", encoding='utf-8')

Itu akan membaca.


3

Meskipun tidak demikian untuk pertanyaan ini, kesalahan ini juga dapat muncul dengan data terkompresi. Secara eksplisit mengatur nilai untuk kwarg compressionmenyelesaikan masalah saya.

result = pandas.read_csv(data_source, compression='gzip')

3

Alternatif yang saya temukan berguna dalam menangani kesalahan parsing serupa menggunakan modul CSV untuk merutekan kembali data menjadi panda df. Sebagai contoh:

import csv
import pandas as pd
path = 'C:/FileLocation/'
file = 'filename.csv'
f = open(path+file,'rt')
reader = csv.reader(f)

#once contents are available, I then put them in a list
csv_list = []
for l in reader:
    csv_list.append(l)
f.close()
#now pandas has no problem getting into a df
df = pd.DataFrame(csv_list)

Saya menemukan modul CSV sedikit lebih kuat untuk file yang dipisahkan koma diformat dengan buruk dan telah berhasil dengan rute ini untuk mengatasi masalah seperti ini.


3

urutan perintah berikut berfungsi (saya kehilangan baris pertama data -tidak ada header = Tidak ada-, tapi setidaknya itu dimuat):

df = pd.read_csv(filename, usecols=range(0, 42)) df.columns = ['YR', 'MO', 'DAY', 'HR', 'MIN', 'SEC', 'HUND', 'ERROR', 'RECTYPE', 'LANE', 'SPEED', 'CLASS', 'LENGTH', 'GVW', 'ESAL', 'W1', 'S1', 'W2', 'S2', 'W3', 'S3', 'W4', 'S4', 'W5', 'S5', 'W6', 'S6', 'W7', 'S7', 'W8', 'S8', 'W9', 'S9', 'W10', 'S10', 'W11', 'S11', 'W12', 'S12', 'W13', 'S13', 'W14']

Berikut ini TIDAK berfungsi:

df = pd.read_csv(filename, names=['YR', 'MO', 'DAY', 'HR', 'MIN', 'SEC', 'HUND', 'ERROR', 'RECTYPE', 'LANE', 'SPEED', 'CLASS', 'LENGTH', 'GVW', 'ESAL', 'W1', 'S1', 'W2', 'S2', 'W3', 'S3', 'W4', 'S4', 'W5', 'S5', 'W6', 'S6', 'W7', 'S7', 'W8', 'S8', 'W9', 'S9', 'W10', 'S10', 'W11', 'S11', 'W12', 'S12', 'W13', 'S13', 'W14'], usecols=range(0, 42))

CParserError: Kesalahan tokenizing data. Kesalahan C: Diharapkan 53 bidang pada baris 1605634, lihat 54 Berikut ini tidak berfungsi:

df = pd.read_csv(filename, header=None)

CParserError: Kesalahan tokenizing data. Kesalahan C: Diharapkan 53 bidang pada baris 1605634, lihat 54

Karenanya, dalam masalah Anda, Anda harus lulus usecols=range(0, 2)


3

Bagi mereka yang memiliki masalah serupa dengan Python 3 di OS linux.

pandas.errors.ParserError: Error tokenizing data. C error: Calling
read(nbytes) on source failed. Try engine='python'.

Mencoba:

df.read_csv('file.csv', encoding='utf8', engine='python')

2

Terkadang masalahnya bukan bagaimana menggunakan python, tetapi dengan data mentah.
Saya mendapat pesan kesalahan ini

Error tokenizing data. C error: Expected 18 fields in line 72, saw 19.

Ternyata dalam uraian kolom terkadang ada koma. Ini berarti bahwa file CSV perlu dibersihkan atau pemisah lain yang digunakan.



1

Saya memiliki dataset dengan nomor baris yang sudah ada, saya menggunakan index_col:

pd.read_csv('train.csv', index_col=0)

1

Inilah yang saya lakukan.

sep='::' memecahkan masalah saya:

data=pd.read_csv('C:\\Users\\HP\\Downloads\\NPL ASSINGMENT 2 imdb_labelled\\imdb_labelled.txt',engine='python',header=None,sep='::')

1

Saya memiliki kasus yang sama seperti ini dan pengaturan

train = pd.read_csv('input.csv' , encoding='latin1',engine='python') 

bekerja


1

Saya memiliki masalah yang sama ketika read_csv: ParserError: Kesalahan tokenizing data. Saya baru saja menyimpan file csv lama ke file csv baru. Masalah terpecahkan!


1

Masalah bagi saya adalah bahwa kolom baru ditambahkan ke CSV saya intraday . Solusi jawaban yang diterima tidak akan berfungsi karena setiap baris di masa depan akan dibuang jika saya gunakan error_bad_lines=False.

Solusi dalam kasus ini adalah dengan menggunakan parameter usecols di pd.read_csv(). Dengan cara ini saya hanya dapat menentukan kolom yang perlu saya baca dalam CSV dan kode Python saya akan tetap tangguh terhadap perubahan CSV di masa mendatang selama ada kolom header (dan nama kolom tidak berubah).

usecols : list-like or callable, optional 

Return a subset of the columns. If list-like, all elements must either
be positional (i.e. integer indices into the document columns) or
strings that correspond to column names provided either by the user in
names or inferred from the document header row(s). For example, a
valid list-like usecols parameter would be [0, 1, 2] or ['foo', 'bar',
'baz']. Element order is ignored, so usecols=[0, 1] is the same as [1,
0]. To instantiate a DataFrame from data with element order preserved
use pd.read_csv(data, usecols=['foo', 'bar'])[['foo', 'bar']] for
columns in ['foo', 'bar'] order or pd.read_csv(data, usecols=['foo',
'bar'])[['bar', 'foo']] for ['bar', 'foo'] order.

Contoh

my_columns = ['foo', 'bar', 'bob']
df = pd.read_csv(file_path, usecols=my_columns)

Manfaat lain dari ini adalah bahwa saya dapat memuat lebih sedikit data ke dalam memori jika saya hanya menggunakan 3-4 kolom dari CSV yang memiliki 18-20 kolom.


1

Resolusi sederhana : Buka file csv di excel & simpan dengan file nama format csv yang berbeda. Sekali lagi coba impor itu spyder, Masalah Anda akan teratasi!


1

Saya mengalami kesalahan ini dengan tanda kutip yang menyimpang. Saya menggunakan perangkat lunak pemetaan yang akan menempatkan tanda kutip di sekitar item teks saat mengekspor file yang dibatasi koma. Teks yang menggunakan tanda kutip (misalnya '= kaki dan "= inci) bisa bermasalah ketika kemudian memicu tabrakan pembatas. Pertimbangkan contoh ini yang mencatat bahwa cetak log sumur 5 inci buruk:

UWI_key,Latitude,Longitude,Remark US42051316890000,30.4386484,-96.4330734,"poor 5""

Menggunakan 5"sebagai singkatan untuk 5 inchakhirnya melemparkan kunci pas dalam karya. Excel hanya akan menghapus tanda kutip tambahan, tetapi Pandas rusak tanpa error_bad_lines=Falseargumen yang disebutkan di atas.


1

Sejauh yang saya tahu, dan setelah melihat file Anda, masalahnya adalah bahwa file csv yang Anda coba muat memiliki beberapa tabel. Ada baris kosong, atau baris yang berisi judul tabel. Coba lihat jawaban Stackoverflow ini . Ini menunjukkan bagaimana mencapainya secara terprogram.

Pendekatan dinamis lain untuk melakukan itu adalah dengan menggunakan modul csv , membaca setiap baris sekaligus dan melakukan pemeriksaan kewarasan / ekspresi reguler, untuk menyimpulkan apakah baris tersebut (judul / header / nilai / kosong). Anda memiliki satu keuntungan lagi dengan pendekatan ini, yaitu Anda dapat membagi / menambahkan / mengumpulkan data Anda dalam objek python seperti yang diinginkan.

Yang paling mudah adalah menggunakan fungsi panda pd.read_clipboard()setelah secara manual memilih dan menyalin tabel ke clipboard, jika Anda dapat membuka csv di excel atau apalah.

Tidak relevan :

Selain itu, tidak relevan dengan masalah Anda, tetapi karena tidak ada yang menyebutkan ini : Saya memiliki masalah yang sama saat memuat beberapa kumpulan data seperti seeds_dataset.txtdari UCI. Dalam kasus saya, kesalahan terjadi karena beberapa pemisah memiliki ruang putih lebih dari tab yang benar \t. Lihat baris 3 pada contoh berikut ini

14.38   14.21   0.8951  5.386   3.312   2.462   4.956   1
14.69   14.49   0.8799  5.563   3.259   3.586   5.219   1
14.11   14.1    0.8911  5.42    3.302   2.7     5       1

Oleh karena itu, gunakan \t+dalam pola pemisah alih-alih \t.

data = pd.read_csv(path, sep='\t+`, header=None)

1

Dalam kasus saya, itu karena format dari dua baris pertama dan terakhir dari file csv berbeda dari konten tengah file.

Jadi yang saya lakukan adalah membuka file csv sebagai string, parsing konten string, lalu gunakan read_csvuntuk mendapatkan dataframe.

import io
import pandas as pd

file = open(f'{file_path}/{file_name}', 'r')
content = file.read()

# change new line character from '\r\n' to '\n'
lines = content.replace('\r', '').split('\n')

# Remove the first and last 2 lines of the file
# StringIO can be considered as a file stored in memory
df = pd.read_csv(StringIO("\n".join(lines[2:-2])), header=None)

1

Dalam kasus saya, pemisah itu bukan default "," tetapi Tab.

pd.read_csv(file_name.csv, sep='\\t',lineterminator='\\r', engine='python', header='infer')

Catatan: "\ t" tidak berfungsi seperti yang disarankan oleh beberapa sumber. "\\ t" diperlukan.


0

Saya memiliki kesalahan yang sama dan masalahnya adalah saya memiliki beberapa kutipan yang lolos dalam file csv saya dan perlu mengatur parameter escapechar dengan tepat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.