mboost-dp1

RegEx (eller noget)


Gå til bund
Gravatar #1 - rackbox
9. jan. 2014 21:50
Er der nogen, der er super hurtige til at parse en html-fil?

Jeg har en fil men en masse linjer af denne slags:


<li onmouseover="OnMouseIn (this)" onmouseout="OnMouseOut (this)">
<div class="singleField">
<div class="colourContent ORACAL" style="background-color: rgb(232,233,238)" >
<div class="rgbval"><span>sRGB:</span> 232, 233, 238</div>
</div>
<div class="colourName"><strong class="colorNo">101 </strong><span class="colorName">arctic white</span></div>
</div>
</li>


Jeg har brug for at trække indholdet i rgb(...,..,..) ud og konvertere det til #FFEEAA (Hex)
Jeg har brug for at trække ColorNo (i dette tilfælde 101) og colorName (i dette tilfælde arctic white) ud

Endelig skal det udformes som en sql query i stil med


insert into colors values('',colorNo,ColorName,Hexvalue)


Jeg er lidt slap i regex... Måske der er en hurtig hjælper her?

PHP er en option...
Gravatar #2 - kasperd
9. jan. 2014 23:50
Har du brug for kode der altid giver korrekte svar? Eller er det nok at det virker nogenlunde korrekt, så længe der ikke ligger overraskelser i nogle af input filerne?

HTML er ikke et regulært sprog, så parsing af HTML vha. regulære udtryk kan aldrig give et eksakt resultat. Og såfremt du skal bruge det på sider fra nettet skal du være opmærksom på, at nettet er fyldt med sider som ikke er gyldigt HTML, så selv hvis du skriver din kode fuldstændigt korrekt, så vil det ikke nødvendigvis virke.

Browsere har historisk set været urimeligt tilgivende overfor dårlig HTML, og det har resulteret i så meget dårligt HTML på nettet, at det i dag er fuldstændigt håbløst at prøve at bruge en rigtig HTML parser i en browser.

Jeg kan foreslå to fremgangsmåder du kan anvende:
1. Find et library til at parse HTML. Et godt library har en option til at fortælle om du vil have at vide såfremt input er ugyldigt eller om du blot vil have det parset til et resultat uanset hvor forkert input måtte være.
2. Brug regex til at tokenize input. Med regex burde det være muligt at identificere den ønskede attribut i det ønskede tag og få værdien ud. Til gengæld vil den kode ikke have den fjerneste anelse om, hvilken kontekst det tag blev fundet i.

Når du har fundet attributværdien bruger du en CSS parser på resultatet. Jeg ved til gengæld ikke om CSS er regulært, men jeg gætter på at det er det nok ikke. Så der har man ca. samme problemstilling igen.

At skrive en komplet HTML parser fra grunden er ikke en fremgangsmåde jeg vil anbefale, for det er et stort stykke arbejde, og det kræver at man ved hvordan man skriver en parser.

Inden du kommer for godt i gang er du nødt til at forstå dine krav og eventuelle begrænsninger i den løsning du har valgt.
Gravatar #3 - Claus Jørgensen
10. jan. 2014 00:39
"rgb\([0-9]{3}\,[0-9]{3}\,[0-9]{3}\)"

Og så find et eller andet lokalt API til at konvertere hex til RPG. Det ville være ubehageligt at skulle skriven koden for det selv.
Gravatar #4 - Claus Jørgensen
10. jan. 2014 00:39
#2

Han skal parse CSS. Så regex er nødvendigt alligevel, selvom du bruger et bibliotek til at parse HTML delen først, for at finde attribute værdien.

Du skriver overdrevne lange indlæg for simple ting.
Gravatar #5 - rackbox
10. jan. 2014 07:54
Den skal faktisk bare bruges et par gange.. Det er i stedet for at taste en ordentlig stak farver ind i en database - og når nu producenten allerede har leveret data på en ordnet måde :)
Gravatar #6 - hundeboll
10. jan. 2014 09:28
Hvis python3 er en mulighed:


#!/usr/bin/env python

import sys
import re

try:
f = sys.argv[1]
except IndexError:
print("Missing argument", file=sys.stderr)
sys.exit(1)

try:
haystack = open(f).read()
except IOError as e:
print(e)
sys.exit(1)

rgb = re.search('(?P<red>\d{3}), (?P<green>\d{3}), (?P<blue>\d{3})', haystack).groups()
no = re.search('"colorNo">(\d+)', haystack).groups()[0]
name = re.search('"colorName">([a-zA-Z0-9 _]+)<', haystack).groups()[0]

rgb = [int(val) for val in rgb]
rgb = "#{:02x}{:02x}{:02x}".format(*rgb)

print("insert into colors values('',{},{},{})".format(no, name, rgb))

(uden line wrap: re.py)
Kør på alle dine filer:


for f in *.html; do ./re.py $f >> insert.sql; done
Gravatar #7 - rackbox
10. jan. 2014 09:42
Jeg har måske 200 farver, der skal ind i en database, og hver farve er beskrevet som i #1
Gravatar #8 - hundeboll
10. jan. 2014 09:47
Aah, jeg missede at det hele stod i samme fil...
Gravatar #9 - rackbox
10. jan. 2014 09:54
Jeg har lige reduceret "kompleksiteten" af den fil, jeg skal parse til sql. Nu ser den således ud:


background-color: rgb(235,220,0)
201 crocus yellow

background-color: rgb(248,205,0)
022 shell yellow

background-color: rgb(245,200,0)
202 mustard yellow

etc...


Skal fortsat brgue noget sql, der ser ud som dette eksempel:
insert into colors values("",201,"crocus yellow","#EBDC00")
Gravatar #10 - hundeboll
10. jan. 2014 10:01
Nu har jeg ellers lige lavet mit python, så den kan parse en enkelt fil med flere <li></li> elementer:
http://bpaste.net/show/166603/
Gravatar #11 - kasperd
10. jan. 2014 11:00
rackbox (5) skrev:
Den skal faktisk bare bruges et par gange.. Det er i stedet for at taste en ordentlig stak farver ind i en database - og når nu producenten allerede har leveret data på en ordnet måde :)
Hvis du bladrer filen igennem både før og efter konvertering og ser at den ser fornuftig ud, så lyder det til at være en situation, hvor det er fornuftigt nok at skære hjørner og ikke lave en fuldstændig parser.

rackbox (9) skrev:
Jeg har lige reduceret "kompleksiteten" af den fil, jeg skal parse til sql. Nu ser den således ud:


background-color: rgb(235,220,0)
201 crocus yellow

background-color: rgb(248,205,0)
022 shell yellow

background-color: rgb(245,200,0)
202 mustard yellow

etc...


Skal fortsat brgue noget sql, der ser ud som dette eksempel:
insert into colors values("",201,"crocus yellow","#EBDC00")
Jeg kom frem til følgende
#!/bin/bash

while read _ RGB && read NUM NAME
do
printf 'insert into colors values("",%s,"%s","#' "$NUM" "$NAME"
for C in $(echo "$RGB" | tr -c 0-9 ' ')
do
printf '%02x' "$C"
done
echo '")'

read BLANK
done
Gravatar #12 - rackbox
10. jan. 2014 11:50
#11 tak, men jeg må nok indrømme at jeg er lidt "read BLANK" på det du skriver :/
Gravatar #13 - mrtb
10. jan. 2014 13:20
Ud fra det output du har i #9, kan http://jsfiddle.net/Kx98U/ så bruges? Tænkte det var nemmest hvis du bare kunne få en fiddle med det :)

Det kunne nok gøres pænere, men det gætter jeg på ikke er så vigtigt, hvis det kun er en engangsting?

Du skal lige angive dine kolonnenavne i outputtet, og nu antog jeg blot at din første kolonne var ID'et.
Gravatar #14 - rackbox
10. jan. 2014 14:39
Tak til alle :) Især #13 - det var nøjagtigt som ønsket - godt tænkt med javascript :)
Gravatar #15 - mrtb
10. jan. 2014 17:48
Det var så lidt :)
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login