Business transparent machen oder ein weiteres Beispiel für Captcha-Erkennung / Sudo Null IT News

Es ist kein Geheimnis, dass Captcha ein beliebtes Tool ist, um die Belastung der Website zu reduzieren und zu verhindern, dass Roboter Informationen herunterladen. Heute, wo Captcha auf fast jeder Website verwendet wird, betrachten wir einen Fall mit Umgehung des Dienstes “Transparentes Geschäft”.

Was ist „Transparentes Geschäft“?

Der Service enthält umfassende Informationen über die finanziellen und rechtlichen Parameter von juristischen Personen (mehr hier). Diese Informationen sind sowohl für die Organisationen selbst nützlich, um Gegenparteien zu überprüfen, als auch für Datenwissenschaftler, um beispielsweise Statistiken zu sammeln und Infografiken für eine bestimmte Region oder ein Land als Ganzes zu erstellen.

Bevor wir beginnen, nehmen wir an, dass wir bereits eine Liste von TINs haben, für die wir den Dienst abfragen müssen. Wenn nicht, können sie entfernt werden Offene Daten des Föderalen Steuerdienstes oder hier.

Auf die Plätze

Beginnen wir mit einer POST-Anforderung für einen Anforderungstext wie folgt:

payload = {‘page’: ‘1’, ‘pageSize’: ’10’, ‘pbCaptchaToken’: ”, ‘token’: ”, ‘mode’: ‘search-ul’, ‘queryAll’: ”, ‘queryUl’: ‘INN FOR QUERY’, ‘okvedUl’: ”, ‘statusUl’: ”, ‘regionUl’: ”, ‘isMspUl’: ”, ‘queryIp’: ”, ‘okvedIp’: ‘ ‘, ‘statusIp’: ”, ‘regionIp’: ”, ‘isMspIp’: ”, ‘mspIp1’: ‘1’, ‘mspIp2’: ‘2’, ‘mspIp3’: ‘3’, ‘queryUpr’ : ”, ‘uprType1’: ‘1’, ‘uprType0’: ‘1’, ‘queryRdl’: ”, ‘dateRdl’: ”, ‘queryAddr’: ”, ‘regionAddr’: ”, ‘queryOgr ‘: ”, ‘ogrFl’: ‘1’, ‘ogrUl’: ‘1’, ‘npTypeDoc’: ‘1’, ‘ogrnUlDoc’: ”, ‘ogrnIpDoc’: ”, ‘nameUlDoc’: ”, ‘nameIpDoc’: ”, ‘formUlDoc’: ”, ‘formIpDoc’: ”, ‘ifnsDoc’: ”, ‘dateFromDoc’: ”, ‘dateToDoc’: ”}

Wenn Sie den Dienst jedoch zu oft ziehen, erhalten wir ein schönes Bild.

die verfügbar sein wird unter https://pb.nalog.ru/static/captcha.bin?r=1664389287469&a=B19F70E11E1ED39188D369F4F698A07A3EF963834C354814A1500080C8EA265EE3109E11270E79BDD6E154 Version.DCB5.DCB5

Der Schlüssel hier ist der Parameter version=2. Versuchen wir es durch version=3 zu ersetzen und erhalten:

Schon besser, oder?

Dann nehmen wir vorläufige Transformationen vor: Wir entfernen den Hintergrund, reinigen ihn von Rauschen und bringen ihn in ein monochromes Aussehen. Es stellt sich so heraus:

Methodencode def clean_image(self): für iy, y in enumerate(self.img_a): für ix, x in enumerate(y): pass if self.img_a[iy][ix][0] > 100 und self.img_a[iy][ix][1] > 100 und self.img_a[iy][ix][2] > 100: self.img_a[iy][ix][0]self.img_a[iy][ix][1]self.img_a[iy][ix][2] = 255, 255, 255 # Streifen löschen, wenn self.img_a[iy][ix][0] >= 27 und self.img_a[iy][ix][0] <= 97 und \self.img_a[iy][ix][1] >= 52 und self.img_a[iy][ix][1] <= 104 und \self.img_a[iy][ix][2] >= 48 und self.img_a[iy][ix][2] <= 117: self.img_a[iy][ix][0]self.img_a[iy][ix][1]self.img_a[iy][ix][2] = 255, 255, 255 # Alles, was übrig bleibt, ist eine Farbe, wenn nicht (self.img_a[iy][ix][0] == 255 und self.img_a[iy][ix][1] == 255 und self.img_a[iy][ix][2] == 255): self.img_a[iy][ix][0]self.img_a[iy][ix][1]self.img_a[iy][ix][2] = 0, 0, 0

Jetzt müssen wir das Bild in Zahlen schneiden. Die Idee ist folgende: Wir scannen das Bild von links nach rechts, die Mitte des ersten vertikalen Streifens aus 5 schwarzen Pixeln in einer Reihe ist der Einstiegspunkt. Finde rekursiv alle benachbarten schwarzen Pixel. Die Grenzen des resultierenden Rechtecks ​​sind die Grenzen unserer Figur. Wenn wir den Vorgang sechsmal (nach der Anzahl der Ziffern) wiederholen, erhalten wir sechs Minibilder (Arrays) mit Zahlen.

Manchmal (eher selten) stellt sich heraus, dass 2 Ziffern in ein Array fallen. Wir erkennen solche Fälle an der überhöhten Breite des Rechtecks ​​(mehr als 35 Pixel), teilen es (Rechteck) in zwei Hälften und hoffen, dass wir Glück haben.

Aus der Praxis ist bekannt, dass die durchschnittliche Größe eines Bildes mit einer Nummer 24 mal 44 Pixel beträgt. Daher wandeln wir es mit der Kissenbibliothek in diese Werte um.

Wir trainieren das neuronale Netz

Wir haben gelernt, wie man Captcha erhält und es in vernünftige Zahlen zerlegt. Aber wie bildet man einen Datensatz zum Trainieren eines Neurons? Und hier kommt uns der Service (pb.nalog.ru) zu Hilfe. Ganz einfach: Jedes Mal, wenn wir ein Captcha herunterladen, erhalten wir ein neues Bild mit denselben Nummern. Mit anderen Worten, wenn wir 10.000 Captchas herunterladen, haben wir 10.000 Optionen, zum Beispiel die Zahl 8. Eine solche Drehung erspart uns das manuelle Daten-Markup, und das ist gut so!

Nehmen wir ein einfaches Modell mit fünf inneren Schichten als Neuron. Dies ist mehr als genug, um eine Genauigkeit von 99 % zu erreichen.

model = keras.Sequential([
keras.layers.Flatten(input_shape=(44, 24)),
keras.layers.Dense(528, activation=’tanh’),
keras.layers.Dense(264, activation=’tanh’),
keras.layers.Dense(132, activation=’tanh’),
keras.layers.Dense(66, activation=’tanh’),
keras.layers.Dense(33, activation=’tanh’),
keras.layers.Dense(10, activation=’softmax’)
]) model.compile(optimizer=”adam”, loss=”categorical_crossentropy”, metrics = [‘accuracy’])

Das trainierte Modell ist auch unter erhältlich GitHub.

Daten bekommen

Wenn wir also das Bild in einen sechsstelligen Code umwandeln können, erhalten wir ein Captcha-Token über eine POST-Anfrage https://pb.nalog.ru/captcha-proc.json

payload = {‘captcha’: CAPTCHA-ERKENNUNGSERGEBNIS}

Dann kehren wir zum Request zurück (von dem aus alles begann), nur leiten wir jetzt im Feld pbCaptchaToken das empfangene Captcha-Token weiter.

Als Antwort wird das Token der Organisation zurückgegeben. Wir übergeben es im Hauptteil der Anfrage per URL

payload = {‘token’: ORGANISATION TOKEN, ‘method’: ‘get-request’}

Hier zeigt der Dienst höchstwahrscheinlich ein weiteres Captcha an. Ja, um an die Daten zu kommen, muss das Captcha zweimal gelöst werden. Aber der Aktionsalgorithmus ist bereits bekannt! Wir lösen das Captcha, übergeben das Captcha-Token mit dem pbCaptchaToken-Feld und erhalten als Antwort ein neues Token und eine neue ID.

Wieder senden wir eine Anfrage an, nur jetzt ist die Methode get-response.

payload = {‘token’: NEW TOKEN, ‘id’: id, ‘method’: ‘get-response’}

Wenn alles gut gelaufen ist, erhalten wir schließlich ein JSON mit Organisationsdaten. Was damit zu tun ist – entscheiden Sie selbst.

Link zu GitHub

Das ist alles!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *