» »

[Python] Kako dekodirat sledeč string?

[Python] Kako dekodirat sledeč string?

HotBurek ::

Dobro jutro.


Evo, preprosti string, kako ga konvertat v bralcu prijazni string?

name = "â\x80\x8eTwilight Princess, Volume â\x80\x8e6â\x80\x8eâ\x80\x8e";

\80\x8e je LRM (LEFT-TO-RIGHT MARK).
‎‎‎‎Python konverta \x80\x8e v oklepaj in mahjno škatlo z diagonalno črto.

Firefox če grem v inspect element, in potem edit, mi prikaže rdečo piko za ta znak.

Kako naj to konvertam v nekaj normalnega?
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
  • spremenilo: HotBurek ()

hbgqzR ::

Ne vem ampak je dobro, da kdo kaj tudi tehničnega sprašuje na slo-tech.com :-)

Po ascii bi to naj bilo € Ž ?? Daj potem entitiziraj ali kaj. Mogoce je sestavljen glif iz vecih znakov?

kow ::

Zakaj nisi prilepil celega stringa v byte obliki? â je ocitno ze interpretiran (z napacnim encodingom).
Sekvence byteov (stringi) lahko interpretiras na vec nacinov. Deterministicno ne mores vedeti kako ga je orig avtor interpretiral, kvecjemu hevristicno.

Ce na hitro ugibam, gre za mesanico japonscine in anglescine (zato tudi LRM znak). Nisem si pa vzel vec kot minuto brskanja. Bo moral povedati kdo, ki se bolje spozna na unicode in encodinge.

Zgodovina sprememb…

  • spremenil: kow ()

HotBurek ::

Kako pa naj naredim capture http response?

Wireshakr mi izpiše ene 50 vrstic, in ne znam ven izluščit zadeve.

Da dodam še to. Če grem v FF v inspect element, potem pa še edit, mi prikaže rdečo piko za ta znak.

Drugje (view-source, wget + nano) prikaže zgolj presledek.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

hbgqzR ::

Naredi si http clienta, ki ti potegne dol kot byte buffer in to zapišeš v binarni file in potem z nekim hex viewerjem pogledaš... Pretvorbe znakov v byte verjetno ni problem naredit ampak tega najbrž nočeš, ker se izgubi s pretvorbo.

HotBurek ::

Sem z wget naredil download, ter uporabil whHexEditor.

Hex: 20 E2 80 8E 54 77 69 6C 69 67 68 74 20 50 72 69 6E 63 65 73 73 2C 20 56 6F 6C 75 6D 65 20 E2 80 8E 36 E2 80 8E E2 80 8E 20
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

hbgqzR ::

Ti tale tvoj
20 E2 80 8E 54 77 69 6C 69 67 68 74 20 50 72 69 6E 63 65 73 73 2C 20 56 6F 6C 75 6D 65 20 E2 80 8E 36 E2 80 8E E2 80 8E 20
ali to kot html entittete
‎Twilight Princess, Volume ‎6‎‎
že karkoli pomeni?

HotBurek ::

Test run:
string = "20E2808E5477696C69676874205072696E636573732C20566F6C756D6520E2808E36E2808EE2808E20";

string2 = bytes.fromhex(string).decode("utf-8");

print("-->>" + (string2) + "<<--");

Output:
-->> ?Twilight Princess, Volume ?6?? <<--

Zanimivo, da PyCharm sploh ne izpiše ? znakov. So vidni šele, ko sem postal na ST.

Problem je, ker bi rad ta končni string peljal žez fukncijo, ko odstrani vsak znak, ki ni črka ali številka. In te grablice (‎) pač ne pašejo zraven.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

hbgqzR ::

če hočeš izpisati v html, moraš entitizirati (malenkostna stvar) - 41 -> &#41; -> A

iteriraj string in odstrani (prepisi v drugi) znake, ki niso iz želenega encoding-character set?

Zgodovina sprememb…

  • spremenilo: hbgqzR ()

HotBurek ::

root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

hbgqzR ::

HotBurek je izjavil:

https://www.jarir.com/simon-schuster-uk...


Izgleda, da lahko ignoriraš takšne specialne znake, najbrž gre za kakšno arabesko, besedilo v trdem je jasno.

Spura ::

HotBurek je izjavil:

https://www.jarir.com/simon-schuster-uk...


Vsak GET s katerim potegnes HTML dokument ima character encoding ali v meta elementu v HTML ali pa v headerjih responsa (content-type). Upostevaj character encoding dokumenta pa ne bo nobenih problemov. To verjetno zna vsaka knjiznjica, ki se ukvarja s tem.

HotBurek ::

Python mi trenutno vrača tole:



In če odstranim znake, ki niso črka ali številko, potem dobim output1, rad pa bi output2.

output1=â twilight princess volume â 6â â
output2=twilight princess volume 6
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

hbgqzR ::

preverjaj, da je koda med 32 in 127 :-)

kuall ::

ukradi kodo iz tu, je pa js.
https://mothereff.in/utf-8

HotBurek ::

HTML: meta http-equiv="Content-Type" content="text/html; charset=utf-8"

HTTP: Content-Encoding: br
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

kuall ::

HotBurek ::

preverjaj, da je koda med 32 in 127 :-)

To je ascii only, rajt?

Ker pol â ni več črka, čeprav je.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

hbgqzR ::

output1=â twilight princess volume â 6â â
output2=twilight princess volume 6


na osnovi output2, ja...
kaj ze sploh ti dejansko pocnes s tem?
scrapas v bazo ali imas live pretvorbo ali kaj?
zdaj bi bilo res fajn, da bi razumeli, kaj dogajas s tem :-)

HotBurek ::

Ja, to ni moja stra. :)

Python pobere HTML dokument in izlušči podatke. Eden od teh je ime (name).

In trenutno Python za zgornji primer (link: link) ta name izpiše kot:


In če iz tega stringa odstraniš vse, kar ni črka ali številka, se prenese črka â, čeprav ta ni vidna (in je krneki, ne paše zraven).

Skratka, korak nazaj.

Kako pofixat Python, da bo iz izvornega HTML dokumenta odstranil šajse znakce, tako, da bo izpisal clean name (Twilight Princess, Volume 6), tako kot ga prikaže brskalnik.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

hbgqzR ::

kot receno, ekstraktaj vsebino z regex iz tistih div-ov in odstrani vse znake, ki niso iz the ascii character set, vpisi preostanek, kamor planiras, in to je to, recimo:

var re =/[^A-Za-z0-9 ]/g;
var t = "â twilight princess volume â 6â â";
console.log(t.replace(re, ""));

Zgodovina sprememb…

  • spremenilo: hbgqzR ()

bluefish ::

Zakaj ne uporabiš scraperja ala beautifulsoup, selenium,...?

Zgodovina sprememb…

  • spremenil: bluefish ()

win64 ::

hbgqzR je izjavil:

kot receno, ekstraktaj vsebino z regex iz tistih div-ov in odstrani vse znake, ki niso iz the ascii character set, vpisi preostanek, kamor planiras, in to je to, recimo:

var re =/[^A-Za-z0-9 ]/g;
var t = "â twilight princess volume â 6â â";
console.log(t.replace(re, ""));

kot rečeno že zgoraj, to odstrani vse ne ascii znake, vključno z šumniki, umlauti..

Boljša rešitev je uporabiti unicode normalizacijo. Če želiš odstranjevati posamezne znake je pa pri delu z unicode najbolj natančno, če v zanki preverjaš kategorijo znaka.
Za python ti žal ne znam podati točnih imen metod.

https://www.unicode.org/reports/tr15/
https://www.compart.com/en/unicode/cate...

HotBurek ::

bs4 ne reši problema, ker izpiše:
[' â\x80\x8eTwilight Princess, Volume â\x80\x8e6â\x80\x8eâ\x80\x8e ']


In iz tega stringa je treba ven dobit vidni string: Twilight Princess, Volume 6

Kar je pa isti problem, kot zgoraj.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

HotBurek ::

Evo, zadevo sem pofixal. Napaka, ali pa nepravilna uporabe funkcije, je bila v sklopu requests modula.

Prej: response.text
Potem: response.content

# make request and get response
response = requests.get(url=url, headers=headers, allow_redirects=True, verify=False, timeout=20);

# put response into beautiful soup
soup = bs4.BeautifulSoup(response.content, features="lxml");

Spremeniš 7 črk, pa začne magično delat. Ful kul, dbest žur.8-)
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

mr_chai ::

HotBurek, lepo da si našel rešitev in naj ti povem eno modrost, ki bi jo moral poznati prav vsak programer, ampak na žalost vidim, da je veliko takih, ki tega ne ve:

String je pol kurca vredn, če ne veš kakšen je njegov encoding!


Razumeš to sedaj v čem je štos ? :)

edit: HotBurek nujno preberi tole https://www.joelonsoftware.com/2003/10/... , čene pridem pa ti dam eno plesko po licu!! obvezno branje

Zgodovina sprememb…

  • spremenilo: mr_chai ()

HotBurek ::

Well, dokumentacija za requests med drugim pravi:

The encoding of the response content is determined based solely on HTTP headers...

Če za omenjeni primer poženem response.encoding, dobim: ISO-8859-1

In če dam ta encoding notri na trdo:
# put response into beautiful soup
soup = bs4.BeautifulSoup(response.content.decode("ISO-8859-1"), features="lxml");

Dobim nazaj tiste šajse znake, s katerim sem imel problem. Če pa dam namesto ISO-8859-1, notri UTF-8 (ali pustim prazno), pa lepo dela.

Skratka web server v header-ju vrača napačen encoding (oz. ga sploh ne), ali pa ga requests modul napačno interpretira.

HTTP vrača zgolj: Content-Type text/html

Fali mu charset.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

hbgqzR ::

win64 je izjavil:


Ja, to je bila namen, glede na to, kako je bilo vprašanje zastavljeno in kakšni primeri so bili dani.

Zgodovina sprememb…

  • spremenilo: hbgqzR ()

Utk ::

HotBurek je izjavil:

Well, dokumentacija za requests med drugim pravi:

The encoding of the response content is determined based solely on HTTP headers...

Če za omenjeni primer poženem response.encoding, dobim: ISO-8859-1

In če dam ta encoding notri na trdo:
# put response into beautiful soup
soup = bs4.BeautifulSoup(response.content.decode("ISO-8859-1"), features="lxml");

Dobim nazaj tiste šajse znake, s katerim sem imel problem. Če pa dam namesto ISO-8859-1, notri UTF-8 (ali pustim prazno), pa lepo dela.

Skratka web server v header-ju vrača napačen encoding (oz. ga sploh ne), ali pa ga requests modul napačno interpretira.

HTTP vrača zgolj: Content-Type text/html

Fali mu charset.

Request že naredi prav, samo stran ima v headerju nekaj, v resnici pa nekaj drugega. Tega kot client ne moreš preprečit.

HotBurek ::

Sedajle sem dve ure programiral rešitev na roko.

Plan je bil sledeč:
- prvo se prebere encoding/charset iz HTTP response-a
- če ga tam ni, gre v HTML meta charset
- če ga tam ni, gre v HTML meta http-equiv
- če ga tam ni, naredi guess

No, sedajle sem našel bolj elegantno rešitev z uporabo apparent_encoding.

Sample:
# init use this charset
use_this_charset = "utf-8";

# set use this charset
if response.apparent_encoding == None:

    # encoding from HTTP response
    use_this_charset = response.encoding.lower();

else:

    # encoding from guessing via chardet
    use_this_charset = response.apparent_encoding.lower();

# put response into beautiful soup
soup = bs4.BeautifulSoup(response.content.decode(use_this_charset), features="lxml");
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

win64 ::

Pa saj ni problem v encodanju.
Bajti "20 E2 80 8E 54 77 69 6C 69 67 68 74 20 50 72 69 6E 63 65 73 73 2C 20 56 6F 6C 75 6D 65 20 E2 80 8E 36 E2 80 8E E2 80 8E 20" so utf8 tekst.
Zdaj kako jih python prikaže v konzoli ali brskalnik na strani/developer konzoli pa je odvisno od aplikacije. Mogoče ti tudi fonti manjkajo, mogoče konzola ne podpira vseh utf8 znakov...

win64 ::

win64 je izjavil:

Pa saj ni problem v encodanju.
Bajti "20 E2 80 8E 54 77 69 6C 69 67 68 74 20 50 72 69 6E 63 65 73 73 2C 20 56 6F 6C 75 6D 65 20 E2 80 8E 36 E2 80 8E E2 80 8E 20" so utf8 tekst.
Zdaj kako jih python prikaže v konzoli ali brskalnik na strani/developer konzoli pa je odvisno od aplikacije. Mogoče ti tudi fonti manjkajo, mogoče konzola ne podpira vseh utf8 znakov...


Če je problem prikaz, pa primer čiščenje niza s pomočjo normalizacije : Š -> S, ä -> a,...
https://wtools.io/paste-code/bFe4

HotBurek ::

Problem je, ker se modul requests zanaša samo na HTTP content-type charset. Če v HTTP header tega ni, naredi fall back na iso-8859-1. Se pravi, ignorira HTML HEAD META informacije.

Končna rešitev:
# set content_type
content_type = response.headers.get("Content-Type", "");

# set use_this_charset
use_this_charset = response.encoding.lower();

# check if use_this_charset is iso-8859-1
if use_this_charset == "iso-8859-1":

    # check if iso-8859-1 is found in http header
    # if not found we know it was fall back
    # so we should try with chardet
    if content_type.lower().find("iso-8859-1") == -1:

        use_this_charset = response.apparent_encoding;

Info: https://github.com/psf/requests/issues/...

The RFC is very clear: if you don't specify a charset, and the MIME type is text/*, the encoding must be assumed to be ISO-8859-1.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Zgodovina sprememb…

  • spremenilo: HotBurek ()

Spura ::

Se mi je zdelo da bo kaj takega. Http kniznjica pac razume le http headerje. Za HTML ne ve da obstaja. Bo pac treba malo na roke preverit kaj v html pise.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Kako narediti request z "\" v URL-ju

Oddelek: Programiranje
172140 (1415) Horejšio
»

Denuvo

Oddelek: Igre
435523 (4595) LeQuack
»

[PHP] charter set windows-1250

Oddelek: Programiranje
282819 (2819) Blisk
»

Zanimiv server LOG

Oddelek: Omrežja in internet
141957 (1525) TheHijacker
»

L0S REzuLTAT0S TU !!! Vsi ki va moja majhna raziskava zanima kojci vržite uč na to ru (strani: 1 2 )

Oddelek: Hlajenje in modifikacije
715361 (4423) texhex

Več podobnih tem