تصدير خطة ترقيم وكالة الاتصالات الفيدرالية إلى قاعدة بيانات علائقية

تقوم وكالة الاتصالات الفيدرالية بانتظام بتحديث خطة الترقيم المتاحة للجمهور . إذا كنت تستخدم هذه الخطة لتحديد المنطقة أو مزود المشترك في خط الاتصال الخاص بك ، فأنت على الأرجح مهتم بمدى صلة هذه المعلومات. للوهلة الأولى ، لا يوجد شيء صعب في كتابة تطبيق يقوم بتنزيل البيانات ومعالجتها وإرسالها إلى قاعدة البيانات ، ومع ذلك ، عند بدء التنفيذ ، ستصادف حتمًا مآزق ، والتي سأتحدث عنها الآن.

تتكون خطة الطلب من أربعة ملفات

جدولة بتنسيق csv: rossvyaz.ru/data/ABC-3xx.csv
rossvyaz.ru/data/ABC-4xx.csv
rossvyaz.ru/data/ABC-8xx.csv
rossvyaz.ru/data/ تتغير

عناوين URL DEF-9xx.csv في بعض الأحيان.

هيكل جميع الجداول هو نفسه:

/ DEF;;;;;

في مجال المنطقة ، يوجد لدى بعض المزودين فواصل منقوطة إضافية:

 ; | ; 

لتجنب حدوث خطأ أثناء قراءة الجدول بواسطة التطبيق الخاص بك ، تحتاج إلى تعطيل التحقق من العدد المتوقع للحقول أو استبدال السجل غير الصحيح بالسجل الصحيح.

سنقوم بكتابة البيانات إلى جدول بالهيكل التالي:

first BIGINT PRIMARY KEY NOT NULL  //  
last BIGINT UNIQUE NOT NULL        //  
provider TEXT                      // 
source_region TEXT                 //        
region INT NOT NULL                //   

يمكن تحديد معظم المناطق في الجداول بشكل لا لبس فيه من خلال حدوث سلسلة فرعية. على سبيل المثال ، تحتوي جميع الإدخالات لمنطقة ساراتوف على السلسلة الفرعية سارات .

بالنسبة لتلك المناطق التي لا يمكن تحديدها بشكل لا لبس فيه ، هناك حاجة إلى منطق إضافي ، حول ذلك أدناه.

مثال 1:

  • Yamal-Nenets Okrug المستقل
  • أوكروغ نينتس المستقل

Okrug Yamalo-Nenets Autonomous Okrug هي جزء من منطقة Tyumen ، و Okrug Nenets Autonomous Okrug جزء من Arkhangelsk. مشكلة تحديد الرمز الرقمي للمنطقة هو أن السلسلة الفرعية Nenets AO مضمنة بالكامل في Yamalo-Nenets AO . هذا يعني أن منطقتين سوف تتطابق مع الإدخالات التي تحتوي على السلسلة الفرعية لمنطقة نينتس المستقلة .

لحل هذه المشكلة ، تحتاج إلى إضافة فحص لعدم وجود سلسلة فرعية (باستثناء السلسلة الفرعية). وبعبارة أخرى ، سيتم تحديد Yamalo-Nenets Autonomous Okrug بدخول Yamalo ، و Nenets Autonomous Okrug بدخول Nenets وغياب Yamalo .

مثال 2:

  • اذهب. كراسنوغورسك
  • ليانتور
  • بارتزا

مثال للمناطق المجهولة. هناك العديد من هذه السجلات في جداول Rossvyaz. مكتشف يساعد على معرفة ذلك GO كراسنوجورسك - منطقة موسكو ، ليانتور - أوكروج خانتي مانسي المستقل ، ومستوطنة بارتز - جمهورية موردوفيا. الحل بسيط ، يتم تحويل السلسلة الفرعية المرغوبة إلى مجموعة من السلاسل ، وسوف نتحقق من حدوثها في حلقة. يتم تحويل السلسلة الفرعية الحصرية أيضًا إلى صفيف.

مثال 3:

  • المقاطعة الفيدرالية السيبيرية ، المقاطعة الفيدرالية الشرقية
  • إقليم كراسنويارسك ، جمهورية خاكاسيا ، موسكو ، سانت بطرسبرغ
  • الاتحاد الروسي

في هذا المثال ، لا يمكن تحديد منطقة بشكل فريد. يمكنك اختيار أكثر قائمة مأهولة بالسكان ، أو تعيين رمز خاص لمثل هذه السجلات. في الواقع ، جميع السجلات التي تتوافق مع العديد من المناطق هي أرقام 8-80 [0-9] ، وهي أرقام اتحادية لا يتم احتساب مكالمات لها. قمت بتعيين رموز لمثل هذه السجلات في النطاق من 200 إلى 210. لا أعتقد أنها ستكون مفيدة لي على الإطلاق.

يمكن العثور على رمز التطبيق هنا .
توجد الملفات القابلة للتنفيذ لمنصات Linux و macos و windows في دليل bin (لم أختبر التطبيق على نظام windows الأساسي).

ملف التكوين Config.ymlيجب أن يكون في نفس الدليل كملف قابل للتنفيذ. إذا كنت ترغب في ذلك ، يمكنك تنفيذ دعم العلامة في التطبيق للإشارة إلى المسار إلى التكوين في وسيطات سطر الأوامر ، نرحب بطلبات السحب.

ملف الضبط
data_source:
  - https://rossvyaz.ru/data/ABC-3xx.csv
  - https://rossvyaz.ru/data/ABC-4xx.csv
  - https://rossvyaz.ru/data/ABC-8xx.csv
  - https://rossvyaz.ru/data/DEF-9xx.csv
#  - ../service/testdata/ABC-3xx.csv
#  - ../service/testdata/ABC-4xx.csv
#  - ../service/testdata/ABC-8xx.csv
#  - ../service/testdata/DEF-9xx.csv
exceptions: exceptions.yml
regions: regions.yml
db:
  host: localhost
  name: asterisk
  table: codes
  user: asterisk
  password: asterisk


يحتوي حقل data_source على المسارات إلى ملفات جدول Rossvyaz. إذا بدأ المسار بـ http ، فسيقوم التطبيق بتحميل الجدول باستخدام عميل الويب المضمن ، وإلا فسيحاول العثور على الجدول في نظام الملفات.

انتبه للخطوط التي تم التعليق عليها. هذه هي مسارات ملفات جدول Rossvyaz المخزنة في المستودع. إذا لم يكن لديك أسرع اتصال بالإنترنت ، فسيعمل كل تطبيق على تنزيل هذه الملفات مرة أخرى. لتطبيق أسرع ، قم بإلغاء تعليق هذه الخطوط والتعليق على الروابط التشعبية. قد تحتاج إلى تشغيل التطبيق أكثر مما تعتقد ، في وقت لاحق سأشرح لماذا استخدام مثال.

الحقول استثناءات و المناطقتحتوي على مسارات للملفات مع تصحيحات ووصف للمناطق. عنهم بعد ذلك بقليل. يصف

قسم db معلمات الاتصال بنظام MySQL DBMS. لاستخدام DBMS آخر ، تحتاج إلى استبدال برنامج التشغيل في التعليمات البرمجية ونموذج سلسلة الاتصال في مُنشئ بنية الخدمة

db, err := dbr.Open("mysql",
		fmt.Sprintf("%s:%s@tcp(%s)/%s", c.DB.User, c.DB.Password, c.DB.Host, c.DB.Name),
		nil)

ومع ذلك ، لا يوجد شيء معقد في إضافة حقل نوع DBMS إلى التكوين وإضافة دعم هذه الأنواع إلى التطبيق ، نرحب بطلبات السحب مرة أخرى.

و exceptions.yml ملف يحتوي على قائمة من الإصلاحات. سيتم استبدال جميع تطابقات السلاسل الفرعية في الاستثناءات .yml قبل القولون ، الموجودة في ملفات جدول Rossvyaz ، بسلاسل فرعية بعد القولون. يحتوي

ملف Regions.yml على قائمة بالرموز الرقمية للمناطق التي تحتوي على صفائف من الأحداث واستبعاد السلاسل الفرعية المستخدمة لتحديد منطقة معينة. إذا لم يتم العثور على سجل لأي سجل أو كان هناك تطابقان أو أكثر ، فسيذهب هذا السجل إلى قاعدة البيانات ، ولكن سيحتوي حقل المنطقة على القيمة 0 (المنطقة غير محددة).

مثال على وصف المنطقة
78:
  name: -
  contain:
    - 
    - 
    - .. 
  not_contain:
    - 


قبل بدء التطبيق ، قم بإنشاء قاعدة بيانات بالاسم المحدد في db.name وتأكد من أن المستخدم المحدد في db.user لديه أذونات القراءة والكتابة.

لذا ، قمنا بإعداد كل شيء ، لقد حان الوقت لبدء التطبيق.

يرجى ملاحظة أنه أثناء بدء التشغيل ، سيتم مسح الجدول المحدد في حقل db.table من ملف التكوين ، كن حذراً.

./def2sql

إذا لم تكن هناك أخطاء وتحذيرات ، فسترى ناتجًا مشابهًا
correct records amount: 372324
inserted 372324 records


وإلا ، سترى تقريرًا يحتوي على أخطاء وتحذيرات.
correct records amount: 372324
inserted 372324 records
{
    "unknown_regions": [
        {
            "First": 3424333950,
            "Last": 3424333999,
            "Range": 50,
            "Provider": " \"\"",
            "SourceRegion": ".. ",
            "Region": 0
        },
        {
            "First": 3424820000,
            "Last": 3424820049,
            "Range": 50,
            "Provider": " \"\"",
            "SourceRegion": ".. ",
            "Region": 0
        },
        {
            "First": 3425425000,
            "Last": 3425425049,
            "Range": 50,
            "Provider": " \"\"",
            "SourceRegion": ".. ",
            "Region": 0
        },
        {
            "First": 3425620000,
            "Last": 3425620049,
            "Range": 50,
            "Provider": " \"\"",
            "SourceRegion": ".. ",
            "Region": 0
        },
        {
            "First": 3426050000,
            "Last": 3426050050,
            "Range": 51,
            "Provider": " \"\"",
            "SourceRegion": ".. ",
            "Region": 0
        },
        {
            "First": 3427399950,
            "Last": 3427399999,
            "Range": 50,
            "Provider": " \"\"",
            "SourceRegion": ".. ",
            "Region": 0
        },
        {
            "First": 4217523500,
            "Last": 4217523999,
            "Range": 500,
            "Provider": " \" \"\"",
            "SourceRegion": " ",
            "Region": 0
        },
        {
            "First": 4217526000,
            "Last": 4217526999,
            "Range": 1000,
            "Provider": " \" \"\"",
            "SourceRegion": " ",
            "Region": 0
        },
        {
            "First": 8003550000,
            "Last": 8003559999,
            "Range": 10000,
            "Provider": " \" \" ( 2460087999)",
            "SourceRegion": "  *   * .  * . -",
            "Region": 0
        },
        {
            "First": 8003810000,
            "Last": 8003819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8013810000,
            "Last": 8013819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8023810000,
            "Last": 8023819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8031010000,
            "Last": 8031019999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8033550000,
            "Last": 8033559999,
            "Range": 10000,
            "Provider": " \" \" ( 2460087999)",
            "SourceRegion": "  *   * .  * . -",
            "Region": 0
        },
        {
            "First": 8033810000,
            "Last": 8033819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8041010000,
            "Last": 8041019999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8043810000,
            "Last": 8043819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8051010000,
            "Last": 8051019999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8053810000,
            "Last": 8053819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8063810000,
            "Last": 8063819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8073810000,
            "Last": 8073819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8083810000,
            "Last": 8083819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8091010000,
            "Last": 8091019999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 8093550000,
            "Last": 8093559999,
            "Range": 10000,
            "Provider": " \" \" ( 2460087999)",
            "SourceRegion": "  *   * .  * . -",
            "Region": 0
        },
        {
            "First": 8093810000,
            "Last": 8093819999,
            "Range": 10000,
            "Provider": " \"\"",
            "SourceRegion": "   *   ",
            "Region": 0
        },
        {
            "First": 9512780000,
            "Last": 9512789999,
            "Range": 10000,
            "Provider": " \"2 \"",
            "SourceRegion": "  *  |  *  ",
            "Region": 0
        },
        {
            "First": 9963000000,
            "Last": 9963029999,
            "Range": 30000,
            "Provider": " \"2 \"",
            "SourceRegion": "  *  |  *  ",
            "Region": 0
        }
    ],
    "warnings": [
        "couldn't find region for record (3424333950-3424333999;  \"\", .. )",
        "couldn't find region for record (3424820000-3424820049;  \"\", .. )",
        "couldn't find region for record (3425425000-3425425049;  \"\", .. )",
        "couldn't find region for record (3425620000-3425620049;  \"\", .. )",
        "couldn't find region for record (3426050000-3426050050;  \"\", .. )",
        "couldn't find region for record (3427399950-3427399999;  \"\", .. )",
        "couldn't find region for record (4217523500-4217523999;  \" \"\",  )",
        "couldn't find region for record (4217526000-4217526999;  \" \"\",  )",
        "couldn't find region for record (8003550000-8003559999;  \" \" ( 2460087999),   *   * .  * . -)",
initial commit
        "couldn't find region for record (8003810000-8003819999;  \"\",    *   )",
        "couldn't find region for record (8013810000-8013819999;  \"\",    *   )",
        "couldn't find region for record (8023810000-8023819999;  \"\",    *   )",
        "couldn't find region for record (8031010000-8031019999;  \"\",    *   )",
        "couldn't find region for record (8033550000-8033559999;  \" \" ( 2460087999),   *   * .  * . -)",
        "couldn't find region for record (8033810000-8033819999;  \"\",    *   )",
        "couldn't find region for record (8041010000-8041019999;  \"\",    *   )",
        "couldn't find region for record (8043810000-8043819999;  \"\",    *   )",
        "couldn't find region for record (8051010000-8051019999;  \"\",    *   )",
        "couldn't find region for record (8053810000-8053819999;  \"\",    *   )",
        "couldn't find region for record (8063810000-8063819999;  \"\",    *   )",
        "couldn't find region for record (8073810000-8073819999;  \"\",    *   )",
        "couldn't find region for record (8083810000-8083819999;  \"\",    *   )",
        "couldn't find region for record (8091010000-8091019999;  \"\",    *   )",
        "couldn't find region for record (8093550000-8093559999;  \" \" ( 2460087999),   *   * .  * . -)",
        "couldn't find region for record (8093810000-8093819999;  \"\",    *   )",
        "couldn't find region for record (9512780000-9512789999;  \"2 \",   *  |  *  )",
        "couldn't find region for record (9963000000-9963029999;  \"2 \",   *  |  *  )"
    ]
}


يحتوي التقرير على عدة أقسام.

unknown_regions - قائمة السجلات التي لا تتوافق مع المناطق ، أو عددها أكثر من واحد ؛
wrong_records - قائمة الإدخالات غير الصالحة في جدول Rossvyaz ؛
تحذيرات - قائمة التحذيرات التي حدثت أثناء تشغيل التطبيق ؛

التقرير تحت المفسد الأخير الذي تلقيته خلال إطلاق التطبيق بعد حوالي شهر من أحدث إصدارات من المناطق .yml .

نسخة قديمة من Regions.yml
1:
  name:   ()
  contain:
    - 
2:
  name:  
  contain:
    - 
    -   
3:
  name:  
  contain:
    - 
4:
  name:  
  contain:
    -  
5:
  name:  
  contain:
    - 
6:
  name:  
  contain:
    - 
7:
  name: - 
  contain:
    - -
8:
  name:  
  contain:
    - 
9:
  name: - 
  contain:
    - 
10:
  name:  
  contain:
    - 
    - .. 
11:
  name:  
  contain:
    - 
12:
  name:   
  contain:
    - 
13:
  name:  
  contain:
    - 
    - . 
14:
  name:   ()
  contain:
    - 
    - 
15:
  name:    - 
  contain:
    - 
16:
  name:   ()
  contain:
    - 
    - 
    - 
17:
  name:  
  contain:
    - 
18:
  name:  
  contain:
    - 
    - . 
19:
  name:  
  contain:
    - 
  not_contain:
    - 
20:
  name:  
  contain:
    -  
    - 
    -  
21:
  name:   - 
  contain:
    -  
    - 
22:
  name:  
  contain:
    -  
23:
  name:  
  contain:
    - 
24:
  name:  
  contain:
    -  
  not_contain:
    - 
25:
  name:  
  contain:
    -  
26:
  name:  
  contain:
    -  
27:
  name:  
  contain:
    - 
28:
  name:  
  contain:
    - 
29:
  name:  
  contain:
    - 
    - 
  not_contain:
    - 
    - 
30:
  name:  
  contain:
    - 
31:
  name:  
  contain:
    - 
32:
  name:  
  contain:
    - 
33:
  name:  
  contain:
    - 
34:
  name:  
  contain:
    - 
35:
  name:  
  contain:
    - 
36:
  name:  
  contain:
    - 
    - .. 
37:
  name:  
  contain:
    - 
    - .. 
    - .. 
38:
  name:  
  contain:
    - 
39:
  name:  
  contain:
    - 
40:
  name:  
  contain:
    - 
41:
  name:  
  contain:
    - 
42:
  name:  
  contain:
    - 
43:
  name:  
  contain:
    - 
44:
  name:  
  contain:
    - 
45:
  name:  
  contain:
    - 
46:
  name:  
  contain:
    - 
#47:
#  name:  
#  contain:
#    - 
48:
  name:  
  contain:
    - 
49:
  name:  
  contain:
    - 
#50:
#  name:  
#  contain:
#    - 
51:
  name:  
  contain:
    - 
52:
  name:  
  contain:
    - 
53:
  name:  
  contain:
    - 
54:
  name:  
  contain:
    - 
    - . 
55:
  name:  
  contain:
    - 
    - . 
56:
  name:  
  contain:
    - 
57:
  name:  
  contain:
    - 
58:
  name:  
  contain:
    - 
59:
  name:  
  contain:
    - 
    - .. 
    -  -
    - - 
60:
  name:  
  contain:
    - 
61:
  name:  
  contain:
    - 
62:
  name:  
  contain:
    - 
63:
  name:  
  contain:
    - 
64:
  name:  
  contain:
    - 
65:
  name:  
  contain:
    - 
66:
  name:  
  contain:
    - 
67:
  name:  
  contain:
    - 
68:
  name:  
  contain:
    - 
69:
  name:  
  contain:
    - 
70:
  name:  
  contain:
    - 
71:
  name:  
  contain:
    - 
72:
  name:  
  contain:
    - 
73:
  name:  
  contain:
    - 
74:
  name:  
  contain:
    - 
    - .. 
    - .. 
75:
  name:  
  contain:
    - 
76:
  name:  
  contain:
    - 
77:
  name: . 
  contain:
    - 
    - 
    - 
    - 
    - .. 
    - .. 
    - .. 
    - .. 
    - .. 
    -    
    - .. 
    - .. 
    - .. 
    -  . 
    - . 
  not_contain:
    - 
78:
  name: -
  contain:
    - 
    - 
    - .. 
  not_contain:
    - 
79:
  name:   
  contain:
    - 
#83:
#  name:   
#  contain:
#    - 
86:
  name: -   - 
  contain:
    - 
    - 
    - 
    - 
    - 
    - . 
  not_contain:
    - 
87:
  name:   
  contain:
    - 
89:
  name: -  
  contain:
    - -
91:
  name:  
  contain:
    -  
    - 
    - 
#92:
#  name: 
#  contain:
#    - 
99:
  name:  ,     
  contain:
    - 

200:
  name:  
  contain:
    - 

201:
  name:   
  contain:
    -   
  not_contain:
    -   
202:
  name:   
  contain:
    -   
  not_contain:
    -   
203:
  name:   
  contain:
    -   
204:
  name:   
  contain:
    -   
  not_contain:
    -   
205:
  name:   
  contain:
    -   
  not_contain:
    -   
206:
  name: -  
  contain:
    - -  
207:
  name:   ,   
  contain:
    -   ,   
208:
  name:   ,   
  contain:
    -   ,   
209:
  name:  ,  , . , . -
  contain:
    -  ,  , . , . -


للتخلص من التحذيرات والحصول على رموز المنطقة لجميع السجلات ، تحتاج إلى تحرير المناطق .

إصدارات مختلفة من Regions.yml
10d9
<     -  
245d243
<     -  
265,270d262
<     - .. 
<     - .. 
<     - .. 
<     - .. 
<     - .. 
<     - .. 
452d443
<     -    *   
457d447
<     -    *   
461,462c451
<     -  ,  , . , . -
<     -   *   * .  * . -
\ No newline at end of file
---
>     -  ,  , . , . -
\ No newline at end of file


هاهو
correct records amount: 372324
inserted 372324 records


ككرز على الكعكة ، أقدم الماكرو Asterisk dialplan لتحديد المنطقة حسب رقم المشترك:

[macro-get-region]
        exten => s,1,MYSQL(Connect conn localhost user password dbname)
        exten => s,n,MYSQL(Query result ${conn} SELECT region FROM codes WHERE ${ARG1} BETWEEN first AND last LIMIT 1)
        exten => s,n,MYSQL(Fetch region ${result} region_num)
        exten => s,n,MYSQL(Clear ${result})
        exten => s,n,MYSQL(Disconnect ${conn})

لنفس الأغراض ، يمكنك استخدام البرنامج النصي Lua:
local driver = require("luasql.mysql")
local env = assert (driver.mysql())
local con = assert (env:connect("dbname", "user", "password"))
local cur = assert (con:execute(string.format("select region from codes where %s between first and last limit 1", arg[1])))

row = cur:fetch ({}, "a")
if row ~= nil then
    print(row.region)
else
    print(0)
end

cur:close()
con:close()
env:close(

ومع ذلك ، فإن أي أداة تدعم استعلامات SELECT لـ MySQL مناسبة.

استمتع بإدارتك.

All Articles