Gorp.NET - perpustakaan baru untuk membuat template terbalik untuk mengekstrak data dari teks terstruktur

Gorp.NET adalah pustaka baru untuk membuat templat yang dapat dibalik untuk mengekstrak data dari teks terstruktur, berdasarkan pada basis kode Salesforce Gorp yang ada.

Dalam publikasi ini, saya akan berbicara sedikit tentang cara menggunakan perpustakaan untuk mem-parsing teks terstruktur yang disebut Gorp (salah satu contoh alat yang kadang-kadang disebut sistem templat rekayasa balik ).
Apakah yang dimaksud dengan template reversibel secara umum? Misalkan kita memiliki sistem tertentu yang memungkinkan kita untuk menghasilkan teks yang kita butuhkan berdasarkan data awal yang telah kita tentukan, sesuai dengan aturan ketat yang ditentukan oleh sintaks templat. Sekarang mari kita bayangkan tugas yang berseberangan dalam arti - kita memiliki teks yang memiliki integritas struktural yang dapat dicapai dengan menggunakan sistem berdasarkan templat dari contoh sebelumnya. Tujuan kami adalah untuk mengekstrak dari teks ini sumber data berdasarkan dari mana data itu dibentuk. Jika kami mencoba memunculkan sintaks umum tertentu untuk menyelesaikan masalah ini, disediakan untuk parser yang sesuai, yang mem-parsing teks input menjadi elemen-elemen terpisah, ini akan menjadi contoh sintaks untuk menerapkan konsep templat yang dapat dibalik.

Mengapa saya memutuskan untuk menulis secara khusus tentang Gorp ? Faktanya adalah saya memutuskan untuk menggunakan sistem ini sebagai dasar untuk menyelesaikan proyek saya sendiri - sejarah proyek itu sendiri, termasuk beberapa perincian dari semua perubahan yang saya buat pada proyek Gorp asli, dapat ditemukan di artikel sebelumnya . Di sini kita akan fokus tepat pada bagian teknis, termasuk mengenai penggunaan versi mesin yang dimodifikasi. Untuk kenyamanan, saya akan terus menyebutnya Gorp.NET , meskipun dalam kenyataannya itu bukan versi Gorp yang tidak porting ke. NET, tetapi hanya versi yang sedikit dipoles dan diselesaikan, semua di Jawa yang sama. Hal lain adalah bahwa add-on di atas pustaka Gorp itu sendiri (dalam versi saya) dalam bentuk pustaka DLL yang dikelola yang disebut BIRMA.NET menggunakan perakitan khusus sendiri - sangat Gorp.NET , yang Anda sendiri dapat dengan mudah dapatkan jika Anda menjalankan teks sumber ( alamat repositori-nya adalah https://github.com/S-presso/gorp/ ) melalui utilitas IKVM.NET .

Saya akan mencatat sekarang bahwa untuk semua jenis tugas mengekstraksi data dari teks terstruktur apa pun, alat Gorp.NET sendiri akan cukup untuk Anda - setidaknya jika Anda memiliki sedikit perintah Java atau setidaknya tahu cara memanggil metode dari modul Java eksternal dalam proyek Anda di NET Framework., Serta menyertakan berbagai jenis dari perpustakaan JVM standar di sana (saya mencapai ini melalui IKVM.NET yang sama, yang, bagaimanapun, sekarang sudah memiliki status proyek yang tidak didukung). Nah, dan apa yang akan Anda lakukan selanjutnya dengan data yang diekstraksi - ini, seperti kata mereka, adalah bisnis pribadi Anda. Gorp dan Gorp.NET sendiri hanya menyediakan kerangka kerja kosong. Beberapa dasar untuk pemrosesan lebih lanjut dari semua data tersebut berisi BIRMA.NET tersebut di atas. Tetapi deskripsi fungsionalitas BIRMA.NET sendiri sudah menjadi topik untuk publikasi terpisah (walaupun saya sudah berhasil menyebutkan sesuatu dalam ulasan komparatif-historis sebelumnya tentang teknologi BIRMA ). Di sini, melihat ke depan, saya akan membiarkan diri saya pernyataan yang agak berani bahwa teknologi yang digunakan untuk menggambarkan template reversibel yang digunakan dalam Gorp.NET (dan, karenanya, dalam BIRMA.NET ) agak unik di antara kerajinan tangan semacam ini (saya katakan “ kerajinan ", karena perusahaan besar entah bagaimana belum terlihat oleh saya dalam mempromosikan kerangka kerja mereka sendiri untuk tujuan ini - yah, mungkin, hanya Tenaga Penjualan itu sendiri dengan implementasi asli Gorp ).

Untuk pengungkapan paling lengkap tentang konsep dan aspek teknis yang mendasari sistem deskripsi templat yang digunakan dalam Gorp, saya hanya meninggalkan tautan di sini ke dokumentasi asli dalam bahasa Inggris . Segala sesuatu yang dinyatakan di dalamnya, Anda dapat dengan aman menerapkan sehubungan dengan Gorp.NET . Dan sekarang saya akan menceritakan sedikit tentang esensinya.

Jadi, deskripsi templat adalah sejenis dokumen teks (bahkan mungkin disajikan sebagai satu garis besar, yang dapat diteruskan ke metode yang sesuai untuk diproses). Ini terdiri dari tiga bagian yang berisi deskripsi berurutan dari tiga entitas yang paling penting: pola , pola , dan sampel (ekstrak).

Blok level terendah di sini adalah pola - mereka hanya dapat terdiri dari ekspresi reguler dan referensi ke pola lain. Level hierarki berikutnya ditempati oleh templat , deskripsi yang juga berisi tautan ke pola, yang juga dapat dinamai, serta penyertaan dalam bentuk literal teks, tautan ke templat dan ekstraktor bersarang. Ada juga pola parametrik yang tidak akan saya sentuh saat ini (dalam dokumentasi sumber ada beberapa contoh penggunaannya). Nah, dan akhirnya, ada sampel yang menentukan aturan sintaksis tertentu yang mengaitkan pola bernama dengan kejadian khusus dari teks sumber.

Seperti yang saya pahami, tujuan awal yang dibuat oleh pencipta Gorp untuk diri mereka sendiri adalah mengurai urutan data yang terkandung dalam file laporan (atau file log). Pertimbangkan contoh sederhana dari aplikasi sistem tertentu.

Misalkan kita memiliki laporan yang berisi baris berikut:

<86> 2015-05-12T20: 57: 53.302858 + 00: 00 10.1.11.141 RealSource: "10.10.5.3"


Mari kita membuat contoh template untuk menguraikannya menggunakan alat Gorp :

pattern %phrase \\S+
pattern %num \\d+\n
pattern %ts %phrase
pattern %ip %phrase

extract interm {
template <%num>$eventTimeStamp(%ts) $logAgent(%ip) RealSource: "$logSrcIp(%ip)"
}


Perhatikan bahwa blok penetapan templat bahkan dihilangkan di sini, karena semua templat yang diperlukan sudah termasuk dalam pemilihan akhir. Semua templat yang digunakan di sini diberi nama, isinya ditunjukkan dalam tanda kurung setelah namanya. Akibatnya, kumpulan data teks akan dibuat dengan nama eventTimeStamp , logAgent dan logSrcIp .

Kami sekarang akan menulis program sederhana untuk mengekstraksi data yang diperlukan. Misalkan templat yang kita buat sudah terkandung dalam file bernama extractions.xtr .
 import com.salesforce.gorp.DefinitionReader; import com.salesforce.gorp.ExtractionResult; import com.salesforce.gorp.Gorp; // ... DefinitionReader r = DefinitionReader.reader(new File("extractions.xtr")); Gorp gorp = r.read(); final String TEST_INPUT = "<86>2015-05-12T20:57:53.302858+00:00 10.1.11.141 RealSource: \"10.10.5.3\""; ExtractionResult result = gorp.extract(TEST_INPUT); if (result == null) { // no match, handle throw new IllegalArgumentException("no match!"); } Map<String,Object> properties = asMap(); // and then use extracted property values 


Contoh lain dari template parsing sederhana:

# Patterns
pattern %num \d+
pattern %hostname [a-zA-Z0-9_\-\.]+
pattern %status \w+

# Templates
@endpoint $srcHost(%hostname): $srcPort(%num)

# Extraction
extract HostDefinition {
template @endpoint $status(%status)
}


Yah, saya pikir intinya jelas. Juga tidak akan salah untuk menyebutkan bahwa untuk metode ekstrak ada juga definisi dengan dua parameter input, yang kedua memiliki tipe logis. Jika Anda menyetelnya menjadi true , maka, ketika dieksekusi, metode ini akan beralih ke semua set data potensial - sampai bertemu dengan yang sesuai (Anda juga dapat mengganti pemanggilan metode dengan extractSafe - sudah tanpa parameter kedua). Standarnya salah , dan metode ini mungkin "bersumpah" pada perbedaan antara data input dan templat yang digunakan.
Saya perhatikan pada saat yang sama bahwa Gorp.NET juga memperkenalkan implementasi metode ekstrak baru yang diperluas: sekarang ada versi dengan dua parameter berikutnya dari tipe logis. Menggunakan panggilan singkat ke tampilan extractAllFound , kami menetapkan keduanya sebagai true secara default. Nilai positif dari parameter ketiga memberi kita ruang lingkup yang lebih besar untuk variasi: mulai sekarang, kita dapat menganalisis teks dengan inklusi karakter sewenang-wenang dalam interval antara sampel yang diinginkan dan sudah terstruktur (berisi set data yang diekstraksi).

Jadi, sudah tiba saatnya untuk menjawab pertanyaan: apa sebenarnya yang bisa menjadi unik dalam modifikasi versi dasar Gorp ini , selain perluasan metode ekstrak?
Faktanya adalah bahwa ketika saya beberapa tahun yang lalu telah membuat semacam alat saya sendiri untuk mengekstraksi data yang diperlukan dari teks (yang juga didasarkan pada pemrosesan templat tertentu dengan sintaksis spesifiknya sendiri), itu bekerja pada prinsip yang sedikit berbeda. Perbedaan utama mereka dari pendekatan yang diterapkan dalam Gorp dan semua kerangka kerja turunannya adalah bahwa setiap elemen teks yang akan diekstraksi diatur hanya dengan mendaftar batas kiri dan kanannya (masing-masing pada gilirannya dapat menjadi bagian dari elemen itu sendiri, atau hanya memisahkannya dari semua teks berikutnya atau sebelumnya). Pada saat yang sama, pada kenyataannya, dalam kasus umum, struktur teks sumber itu sendiri tidak dianalisis, seperti halnya dalam Gorp , tetapi hanya potongan-potongan yang diperlukan yang dipilih. Adapun konten teks yang terlampir di antara mereka, itu tidak bisa menyerah pada analisis struktural sama sekali (itu bisa jadi set karakter yang tidak koheren).

Apakah mungkin untuk mencapai efek serupa di Gorp ? Dalam versi awalnya - mungkin tidak (koreksi saya jika saya salah tentang ini). Jika kita cukup menulis ekspresi seperti (. *) , Diikuti dengan segera oleh mask untuk menentukan batas kiri elemen berikutnya yang akan dicari, kemudian dengan menggunakan quantifier "greed", seluruh teks selanjutnya akan ditangkap. Dan kita tidak bisa menggunakan pelanggan tetap dengan sintaks "non-rakus" dalam implementasi Gorp yang ada.
Gorp.NET memungkinkan Anda untuk dengan lancar menghindari masalah ini dengan memperkenalkan dua jenis pola khusus - (% all_before) dan (% all_after) . Yang pertama, sebenarnya, adalah alternatif untuk versi "tidak serakah" (. *) , Cocok untuk digunakan dalam menyusun template Anda sendiri. Adapun (% all_after) , ia juga melihat teks sumber sampai kemunculan pertama dari bagian berikutnya dari pola yang dijelaskan - tetapi sudah mengandalkan hasil pencarian dari pola sebelumnya. Segala sesuatu yang ada di antara mereka juga akan jatuh ke substring yang dapat diekstraksi dari elemen saat ini. Dalam arti (% all_after) "melihat ke belakang", dan (% all_before) , sebaliknya, "berharap". Saya perhatikan bahwa analog unik untuk (% all_before) dalam versi pertama BIRMA adalah batas kiri yang hilang dalam deskripsi elemen, dan analog (% all_after) , masing-masing, adalah kekosongan alih-alih batas kanan. Jika kedua batas tidak disetel saat mendeskripsikan elemen berikutnya, maka pengurai jelas menangkap semua teks selanjutnya! Namun, semua ini maka implementasi BIRMA sekarang memiliki signifikansi historis murni (Anda dapat membaca lebih banyak tentang hal itu dalam laporan saya saat itu ).
Teks tersembunyi
Kode sumber tidak pernah diletakkan di mana pun karena kualitasnya yang sangat rendah - sebenarnya, mereka dapat berfungsi sebagai monumen untuk desain sistem perangkat lunak yang buruk.


Mari kita lihat fitur menggunakan pola layanan (% all_before) dan (% all_after) menggunakan contoh tugas mengekstraksi data pengguna tertentu dari situs web tertentu. Kami akan mem-parsing situs Amazon, dan secara khusus halaman ini: https://www.amazon.com/B06-Plus-Bluetooth-Receiver-Streaming/product-reviews/B078J3GTRK/ ).
Teks tersembunyi
Contoh diambil dari tugas pengujian untuk lowongan pengembang dengan spesialisasi dalam penguraian data, yang dikirim oleh perusahaan saya, yang, sayangnya, belum menanggapi solusi yang saya usulkan untuk masalah tersebut. Benar, mereka hanya meminta saya untuk menggambarkan proses umum dari solusi - tanpa menyediakan algoritma spesifik, dan sebagai tanggapan saya sudah mencoba merujuk ke template Gorp, sedangkan ekstensi saya sendiri pada waktu itu hanya ada, seperti yang mereka katakan, "di atas kertas" ".
Demi rasa ingin tahu, saya akan membiarkan diri mengutip satu fragmen dari surat balasan saya, yang, tampaknya, adalah penyebutan pertama dari Gorp.NET , meskipun bersifat pribadi.
"Untuk membuat daftar ekspresi reguler di atas yang digunakan oleh saya untuk menyelesaikan masalah ini lebih visual, saya menyusun template yang sudah jadi atas dasar (melampirkannya pada surat), yang dapat digunakan untuk mengekstrak semua data yang diperlukan dengan menerapkan pengembangan saya sendiri yang bersifat lebih universal, hanya dirancang untuk memecahkan masalah jenis ini. Kodenya didasarkan pada proyek github.com/salesforce/gorp , dan pada halaman yang sama ada deskripsi umum tentang aturan untuk mengkompilasi templat tersebut. Secara umum, deskripsi seperti itu sendiri menyiratkan penugasan ekspresi reguler konkret dan logika pemrosesan mereka. Poin yang paling sulit di sini adalah bahwa untuk setiap sampel data, kita harus benar-benar menggambarkan melalui reguler seluruh struktur teks yang memuatnya, dan bukan hanya elemen individu itu sendiri (seperti yang dapat dilakukan saat menulis program kita sendiri yang mencari secara berurutan dalam satu lingkaran, seperti saya). dijelaskan sebelumnya). "

Tugas asli adalah mengumpulkan data berikut dari halaman di atas:

  • Nama pengguna
  • Peringkat
  • Judul Ulasan
  • Tanggal
  • Teks


Nah, sekarang saya hanya akan memberi Anda template yang dikompilasi oleh saya, yang memungkinkan Anda menyelesaikan tugas ini dengan cepat dan efisien. Saya pikir makna umum harus cukup jelas - mungkin Anda sendiri dapat menawarkan solusi yang lebih ringkas.
Teks tersembunyi
Pada contoh ini bahwa, secara umum, saya mendebug fungsi dari ekstensi saya sendiri untuk Gorp (sudah tanpa tujuan untuk pekerjaan, tetapi lebih didasarkan pada ideologi "Bukti Konsep").


pattern %optspace ( *)
pattern %space ( +)

pattern %cap_letter [AZ]
pattern %small_letter [az]
pattern %letter (%cap_letter|%small_letter)
pattern %endofsentence (\.|\?|\!)+
pattern %delim (\.|\?|\!\,|\:|\;)
pattern %delim2 (\(|\)|\'|\")

pattern %word (%letter|\d)+
pattern %ext_word (%delim2)*%word(%delim)*(%delim2)*

pattern %text_phrase %optspace%ext_word(%space%ext_word)+
pattern %skipped_tags <([^>]+)>

pattern %sentence (%text_phrase|%skipped_tags)+(%endofsentence)?

pattern %start <div class=\"a-fixed-right-grid view-point\">

pattern %username_start <div class=\"a-profile-content\"><span class=\"a-profile-name\">
pattern %username [^\s]+
pattern %username_end </span>

pattern %user_mark_start <i data-hook=\"review-star-rating\"([^>]+)><span class=\"a-icon-alt\">
pattern %user_mark [^\s]+
pattern %user_mark_end ([^<]+)</span>

pattern %title_start data-hook=\"review-title\"([^>]+)>(%skipped_tags)*
pattern %title [^<]+
pattern %title_end </span>

pattern %span class <span class=\"[^\"]*\">

pattern %date_start <span data-hook="review-date"([^>]+)>
pattern %date ([^<]+)
pattern %date_end </span>

pattern %content_start <span data-hook=\"review-body\"([^>]+)>(%skipped_tags)*
pattern %content0 (%sentence)+
pattern %content (%all_after)
pattern %content_end </span>

template @extractUsernameStart (%all_before)%username_start
template @extractUsername $username(%username)%username_end
template @extractUserMarkStart (%all_before)%user_mark_start
template @extractUserMark $user_mark(%user_mark)%user_mark_end
template @extractTitleStart (%all_before)%title_start
template @extractTitle $title(%title)%title_end
template @extractDateStart (%all_before)%date_start
template @extractDate $date(%date)%date_end
template @extractContentStart (%all_before)%content_start
template @extractContent $content(%content)%content_end

extract ToCEntry {
template @extractUsernameStart@extractUsername@extractUserMarkStart@extractUserMark@extractTitleStart@extractTitle@extractDateStart@extractDate@extractContentStart@extractContent
}



Mungkin itu saja untuk hari ini. Tentang alat pihak ketiga yang telah saya terapkan, di mana kerangka kerja ini telah sepenuhnya terlibat, saya dapat memberi tahu Anda lain kali.

Source: https://habr.com/ru/post/id476778/


All Articles