Соответствие регулярному выражению для структурированных элементов JSON - PullRequest
1 голос
/ 06 мая 2019

У меня проблема с тем, что я пытаюсь взять длинную многострочную строку, использовать кучу замен регулярных выражений, чтобы сделать ее (близкий, но не идеальный) формат JSON, перед извлечением элементов регулярного выражения.

Строка - это необработанные данные whois, извлекаемые из домена, я пытаюсь получить такие вещи, как дата истечения срока действия и т. Д. (Whois имеет много нюансов, которые я собираюсь пропустить, например, более 1200 серверов whois для разных TLD,каждый с разными форматами и т. д.)

Кажется, моя функция работает для одного домена, но когда я использую функцию в цикле for, я получаю действительно ошибочные результаты.Я не уверен, связано ли это с каким-либо ограничением регулярных выражений или чем-то в скриптах приложений, или у меня что-то не так.

Пример строки после начальной обработки:

(var newString =)

{"DomainName": "WANITAMALAS.COM", "RegistryDomainID": "2115163838_DOMAIN_COM-VRSN", "RegistrarWHOISServer": "whois.PublicDomainRegistry.com", "RegistrarURL ":" www.publicdomainregistry.com " "UpdatedDate": "2019-04-14T10: 02: 49Z", "CreationDate": "2017-04-17T15: 35: 40Z", "RegistryExpiryDate":" 2020-04-17T15: 35: 40Z " "Регистратор": "PDRLtd.dbaPublicDomainRegistry.com", "RegistrarIANAID": "303", "RegistrarAbuseContactEmail": "abuse-contact@publicdomainregistry.com", "RegistrarAbuseContactPhone":" + 1,2013775952», "DomainStatus": "clientTransferProhibitedicann.orgepp # clientTransferProhibited", "NAMESERVER1": "BAYAN.NS.CLOUDFLARE.COM", "NAMESERVER2": "LORNA.NS.CLOUDFLARE.COM", "DNSSEC": "без знака","URLoftheICANNWhoisInaccuracyComplaintForm": "www.icann.orgwicf", ">>> Lastupdateofwhoisdatabаза ":" 2019-05-06T13: 55: 16Z <<<», "FormoreinformationonWhoisstatuscodespleasevisiticann.orgepp", "ВНИМАНИЕ": "Theexpirationdatedisplayedinthisrecordisthedatethe", "registrar'ssponsorshipofthedomainnameregistrationintheregistryis", "currentlysettoexpire.Thisdatedoesnotnecessarilyreflecttheexpiration", "dateofthedomainnameregistrant'sagreementwiththesponsoring","registrar.Usersmayconsultthesponsoringregistrar'sWhoisdatabaseto", "viewtheregistrar'sreporteddateofexpirationforthisregistration.", "TERMSOFUSE": "YouarenotauthorizedtoaccessorqueryourWhois", "databasethroughtheuseofelectronicprocessesthatarehigh-volumeand", "automatedexceptasreasonablynecessarytoregisterdomainnamesor", "modifyexistingregistrations; theDatainVeriSignGlobalRegistry", "Услуги (\ "VeriSign \") WhoisdatabaseisprovidedbyVeriSignfor" "informationpurposesonlyandtoassistpersonsinobtaininginformation", "aboutorrelatedtoadomainnameregistrationrecord.VeriSigndoesnot", "guaranteeitsaccuracy.BysubmittingaWhoisqueryyouagreetoabide"," bythefollowingtermsofuse ":" YouagreethatyoumayusethisDataonly», "forlawfulpurposesandthatundernocircumstanceswillyouusethisData", "до": "(1) allowenableorotherwisesupportthetransmissionofmass", "unsolicitedcommercialadvertisingorsolicitationsviae-mailtelephone", "orfacsimile, или (2) enablehighvolumeautomatedelectronicprocesses", "thatapplytoVeriSign (oritscomputersystems) .Thecompilation", "repackagingdisseminationorotheruseofthisDataisexpressly", "prohibitedwithoutthepriorwrittenconsentofVeriSign.Youagreenotto", "useelectronicprocessesthatareautomatedandhigh-volumetoaccessor", "querytheWhoisdatabaseexceptasreasonablynecessarytoregister", "domainnamesormodifyexistingregistrations.VeriSignreservestheright", "torestrictyouraccesstotheWhoisdatabaseinitssolediscretiontoensure", "operationalstability.VeriSignmayrestrictorterminateyouraccesstothe", "Whoisdatabaseforfailuretoabidebythesetermsofuse.VeriSign", "reservestherighttomodifythesetermsatanytime.", "TheRegistrydatabasecontainsONLY.COM.NET.EDUdomainsand», "Регистраторы.", ""}</p>

Моя функция:

function processAllDomains(){
    //Bunch of Sheets stuff here...//
    for(var i = 0 ; i< urlsList.length ; ++){
        whoisDataLookup(urlsList[i],"-"); // Second argument "Status" can be an error from a previous step in the process
    }
    //Do stuff//
}
function whoisDataLookup(domain,status) {
    var whoisData = [domain, status];

    whoisData.push(new Date());
    var CAYKwhoIsServer = "https://myHerokuWhoisApp.com/";

    var regexChecks = [];
    var Registrar = /(?:Registrar|RegistryDomainID|SponsoringRegistrar)":"(.*?)",/gim
        regexChecks.push(Registrar);

    var RegistrarURL = /(?:RegistrarWHOISServer|RegistrarURL)":"(.*?)",/gim
        //  var RegistrarWhoisUrl = /RegistrarWHOISServer":"(.*?)",/gi
        regexChecks.push(RegistrarURL);

    var UpdatedDate = /(?:UpdatedDate|Lastupdatedon)":"(.*?)",/gim
        regexChecks.push(UpdatedDate);

    var CreationDate = /(?:CreationDate|created|RegistrationTime)":"(.*?)",/gim
        regexChecks.push(CreationDate);

    var RegistryExpiryDate = /(?:RegistryExpiryDate|paid-till|ExpirationTime)":"(.*?)",/gim
        regexChecks.push(RegistryExpiryDate);

    var NameServer1 = /NameServer1":"(.*?)",/gim
        regexChecks.push(NameServer1);

    var NameServer2 = /NameServer2":"(.*?)",/gim
        regexChecks.push(NameServer2);

    var DNSSEC = /DNSSEC":"(.*?)",/gim
        regexChecks.push(DNSSEC);

    var fetchURL = CAYKwhoIsServer + domain;
    Logger.log('fetchURL is: ' + fetchURL);
    if (status != "-") { // If not null mark, then an error exists, so null the whole row
        for (var d = 0; d < regexChecks.length + 2; ++d) {
            whoisData.push("-")
        }
        return whoisData;
    }

    var whoisFetch = UrlFetchAppCacheToDrive(fetchURL, domain + "--whois") // just a url fetch, but saves the fetched content to Google drive, then if the same url is requested in future, pull the drive content, instead of fetching it from the web again.
        //    Logger.log('whoisFetch is: ' + whoisFetch);
        var whoisJSON = JSON.parse(whoisFetch);
    // Logger.log(whoisJSON.keys);


    var whoisString = JSON.stringify(whoisJSON["result"]); // the whois pulls other stuff, only the result is the actual whois string
    //   Logger.log('whoisString is: ' + whoisString);
    if (whoisString == undefined) {
        whoisString = "-";
    }

    whoisData.push(whoisString);

    try {
        whoisString = whoisString.replace(/ /g, '');
        whoisString = whoisString.replace(/\,/g, '');

        if (whoisString.match("WhoisdServerVersion")) {
            whoisString = whoisString.replace(/.*WhoisdServerVersion/, '"WhoisdServerVersion');
            whoisString = whoisString.replace(/\(.*\)/, '');

        }
// Start a bunch of whois string cleanup, working towards the sample string shown above.
        whoisString = whoisString.replace(/.*\(\w\:\)/, '$1');
        whoisString = whoisString.replace(/\%/g, '');
        whoisString = whoisString.replace(/\\r/gi, '');
        whoisString = whoisString.replace(/\\n\\n/g, '\\n');
        whoisString = whoisString.replace(/\\n\\n/g, '\\n');
        whoisString = whoisString.replace(/\\n\\n/g, '\\n');
        whoisString = whoisString.replace(/\\n$/, '');
        //    Logger.log('whoisString Check is: ' + whoisString);
        whoisString = whoisString.replace(/https?:\/\//gi, '');
        whoisString = whoisString.replace(/\//gi, '');
        whoisString = whoisString.replace(/(\d\d)\:/gi, "$1qqqqqqqqqq"); // temporarily replace some COLON (:), to be sure we do not split up the string based on IPV6 ip addresses, which sometimes appear in whois string.
        whoisString = whoisString.replace(/NameServers?:/i, 'NameServer1:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer2:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer3:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer4:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer5:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer6:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer7:');
        whoisString = whoisString.replace(/NameServer:/i, 'NameServer8:');
        whoisString = whoisString.replace(/:/g, '":"');
        whoisString = whoisString.replace(/":"\\n/g, '":"');
        whoisString = whoisString.replace(/qqqqqqqqqq/gi, ":");
        whoisString = whoisString.replace(/\\n/gi, '","');
        // whoisString = whoisString.replace(/,""$/,'');


        var newString = "{" + whoisString + "}";



    } catch (e) {
        whoisData.splice(1, 1, "WhoisLookupError")
    }
    if (newString) {
        whoisData.push(newString);
    } else {
        whoisData.push('-')
    }
// **Everything seems to work as expected to this point, as my output shows 
// newString properly in all cases, from here, it gets wonky though.**

    for (var e = 0; e < regexChecks.length; ++e) {
        Utilities.sleep(50)
        var regexCheck = regexChecks[e];
        //  Logger.log('regexCheck is: ' + regexCheck);
        var metric = regexCheck.exec(newString);

        if (metric != undefined) {
            Logger.log(regexCheck + ' metric found is: ' + metric[1]);
            whoisData.push(metric[1])
        } else {
            Logger.log(regexCheck + ' metric not found');

            whoisData.push('-');
        }
    }
    return whoisData;

}

Example Output showing erratic regex matching, when values exist and when regex101.com shows the regex should have matched.

Вот пример одного регулярного выраженияmatch, который вошел как undefined: (меня не очень беспокоит несколько совпадений, просто нужно что-то в поле на данный момент) Here is an example of a single regex match, which logged as undefined

1 Ответ

1 голос
/ 07 мая 2019

Я бы продолжил путь, чтобы сделать его действительным JSON. Заданная вами строка является допустимым JSON, за исключением одного повторяющегося шаблона:

Некоторые длинные строковые литералы, кажется, разбиты на несколько строковых литералов, разделенных запятыми. Если бы вы могли просто заключить эти серии в квадратные скобки, они бы сформировали правильный массив.

Вот как это будет работать:

// The string you provided in the question:
var newString = `{"DomainName":"WANITAMALAS.COM","RegistryDomainID":"2115163838_DOMAIN_COM-VRSN","RegistrarWHOISServer":"whois.PublicDomainRegistry.com","RegistrarURL":"www.publicdomainregistry.com","UpdatedDate":"2019-04-14T10:02:49Z","CreationDate":"2017-04-17T15:35:40Z","RegistryExpiryDate":"2020-04-17T15:35:40Z","Registrar":"PDRLtd.dbaPublicDomainRegistry.com","RegistrarIANAID":"303","RegistrarAbuseContactEmail":"abuse-contact@publicdomainregistry.com","RegistrarAbuseContactPhone":"+1.2013775952","DomainStatus":"clientTransferProhibitedicann.orgepp#clientTransferProhibited","NameServer1":"BAYAN.NS.CLOUDFLARE.COM","NameServer2":"LORNA.NS.CLOUDFLARE.COM","DNSSEC":"unsigned","URLoftheICANNWhoisInaccuracyComplaintForm":"www.icann.orgwicf",">>>Lastupdateofwhoisdatabase":"2019-05-06T13:55:16Z<<<","FormoreinformationonWhoisstatuscodespleasevisiticann.orgepp","NOTICE":"Theexpirationdatedisplayedinthisrecordisthedatethe","registrar'ssponsorshipofthedomainnameregistrationintheregistryis","currentlysettoexpire.Thisdatedoesnotnecessarilyreflecttheexpiration","dateofthedomainnameregistrant'sagreementwiththesponsoring","registrar.Usersmayconsultthesponsoringregistrar'sWhoisdatabaseto","viewtheregistrar'sreporteddateofexpirationforthisregistration.","TERMSOFUSE":"YouarenotauthorizedtoaccessorqueryourWhois","databasethroughtheuseofelectronicprocessesthatarehigh-volumeand","automatedexceptasreasonablynecessarytoregisterdomainnamesor","modifyexistingregistrations;theDatainVeriSignGlobalRegistry","Services'(\\\"VeriSign\\\")WhoisdatabaseisprovidedbyVeriSignfor","informationpurposesonlyandtoassistpersonsinobtaininginformation","aboutorrelatedtoadomainnameregistrationrecord.VeriSigndoesnot","guaranteeitsaccuracy.BysubmittingaWhoisqueryyouagreetoabide","bythefollowingtermsofuse":"YouagreethatyoumayusethisDataonly","forlawfulpurposesandthatundernocircumstanceswillyouusethisData","to":"(1)allowenableorotherwisesupportthetransmissionofmass","unsolicitedcommercialadvertisingorsolicitationsviae-mailtelephone","orfacsimile;or(2)enablehighvolumeautomatedelectronicprocesses","thatapplytoVeriSign(oritscomputersystems).Thecompilation","repackagingdisseminationorotheruseofthisDataisexpressly","prohibitedwithoutthepriorwrittenconsentofVeriSign.Youagreenotto","useelectronicprocessesthatareautomatedandhigh-volumetoaccessor","querytheWhoisdatabaseexceptasreasonablynecessarytoregister","domainnamesormodifyexistingregistrations.VeriSignreservestheright","torestrictyouraccesstotheWhoisdatabaseinitssolediscretiontoensure","operationalstability.VeriSignmayrestrictorterminateyouraccesstothe","Whoisdatabaseforfailuretoabidebythesetermsofuse.VeriSign","reservestherighttomodifythesetermsatanytime.","TheRegistrydatabasecontainsONLY.COM.NET.EDUdomainsand","Registrars.",""}`;

// Turn the series of string literals into arrays of strings:
var json = newString.replace(/":\s*("(?:\\.|[^"])*"(?:,\s*"(?:\\.|[^"])*")+)(?!\s*:)/g, '": [$1]');

// Parse
var obj = JSON.parse(json);

console.log(obj);

Некоторые ключи / значения выглядят немного странно, так как они кажутся частью более длинного текста, пробел которого был удален. Возможно, вы могли бы получить лучшие результаты, если бы по-другому относились к (неизвестной) исходной строке. Но этот объект, по крайней мере, позволит вам легко извлечь то, что вам нужно:

console.log(obj.DomainName);
console.log(obj.UpdatedDate);
// ...
...