Я преобразовал PDF-файл в HTML-файл с помощью встроенных инструментов Adobe, но я изо всех сил пытаюсь написать функции регулярного выражения для захвата различных данных:
ОСНОВНАЯ ПРОБЛЕМА: многие элементы HTML вместе с текстом между ними занимают несколько строк, поэтому регулярное выражение часто пропускается.
(Примечание: HTML-документ содержит список музыкальных фестивалей и их соответствующие детали)
Мой текущий код работает следующим образом:
<h1 style='margin-top:7.3pt;margin-right:0in;margin-bottom:0in;margin-left:
61.0pt;margin-bottom:.0001pt'><a name=ALABAMA></a><a name = "_bookmark0"></a>ALABAMA</h1>
<p class=MsoBodyText style='margin-top:.2pt'><b style='mso-bidi-font-weight:
normal'><span style='font-size:35.0pt;mso-bidi-font-size:11.0pt'><o:p> </o:p></span></b></p>
<h5 style='margin-left:61.0pt'><a name=Alabaster></a><a name = "_bookmark1"></a><span
style='color:#FF2500'>Alabaster</span></h5>
<p class=MsoBodyText style='margin-top:.15pt'><b style='mso-bidi-font-weight:
normal'><i style='mso-bidi-font-style:normal'><span style='font-size:12.5pt;
mso-bidi-font-size:11.0pt'><o:p> </o:p></span></i></b></p>
<p class=MsoNormal style='margin-top:0in;margin-right:73.45pt;margin-bottom:
0in;margin-left:61.0pt;margin-bottom:.0001pt;line-height:101%'><b
style='mso-bidi-font-weight:normal'><span style='font-size:14.0pt;mso-bidi-font-size:
11.0pt;line-height:101%'>Takeoff Fest </span></b><a
href = "mailto:[email protected]"><span style='font-size:12.0pt;
mso-bidi-font-size:11.0pt;line-height:101%;color:blue'>[email protected]</span></a><a
href = "mailto:[email protected]"><span style='color:blue'>m</span></a><span
style='color:blue'> </span>Festival Month(s): <i style='mso-bidi-font-style:
normal'>June<o:p></o:p></i></p>
<p class=MsoBodyText style='margin-top:.05pt'><i style='mso-bidi-font-style:
normal'><span style='font-size:13.5pt;mso-bidi-font-size:11.0pt'><o:p> </o:p></span></i></p>
<h5 style='margin-left:61.0pt'><a name=Albertville></a><a name = "_bookmark2"></a><span
style='color:#FF2500'>Albertville</span></h5>
<p class=MsoBodyText style='margin-top:.4pt'><b style='mso-bidi-font-weight:
normal'><i style='mso-bidi-font-style:normal'><span style='font-size:12.5pt;
mso-bidi-font-size:11.0pt'><o:p> </o:p></span></i></b></p>
<h6 style='margin-top:0in;margin-right:34.05pt;margin-bottom:0in;margin-left:
61.0pt;margin-bottom:.0001pt;line-height:105%'>Albertville Main Street Music
Festival</h6>
<p class=MsoBodyText style='margin-top:.2pt;margin-right:73.45pt;margin-bottom:
0in;margin-left:61.0pt;margin-bottom:.0001pt'><a
href = "mailto:[email protected]"><span style='color:windowtext;
text-decoration:none;text-underline:none'>[email protected]</span></a>
Festival Month(s):<i style='mso-bidi-font-style:normal'>August<o:p></o:p></i></p>
<p class=MsoBodyText style='margin-top:.3pt'><i style='mso-bidi-font-style:
normal'><span style='font-size:12.5pt;mso-bidi-font-size:11.0pt'><o:p> </o:p></span></i></p>
<h6 style='margin-left:61.0pt'>Main Street Music Festival</h6>
<p class=MsoNormal style='margin-top:.2pt;margin-right:-.95pt;margin-bottom:
0in;margin-left:61.0pt;margin-bottom:.0001pt;line-height:100%'><a
href = "http://www.mainstreetmusicfestival.com/e%20ntertainment.html"><span
style='font-size:10.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>http://www.mainstreetmusicfestival.com/e</span></a><span
style='font-size:10.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>
</span><a href = "http://www.mainstreetmusicfestival.com/e%20ntertainment.html"><span
style='font-size:10.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>ntertainment.html</span></a><span
style='font-size:10.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>
</span><a href = "mailto:[email protected]"><span
style='color:windowtext;text-decoration:none;text-underline:none'>[email protected]</span></a>
<b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:normal'><span
style='font-size:12.0pt;mso-bidi-font-size:11.0pt;line-height:100%'>Note: </span></i></b><i
style='mso-bidi-font-style:normal'><span style='font-size:12.0pt;mso-bidi-font-size:
11.0pt;line-height:100%'>Submissions open through June (online only).<o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:61.0pt;line-height:13.2pt;mso-line-height-rule:
exactly'>Festival Month(s): <i style='mso-bidi-font-style:normal'>August<o:p></o:p></i></p>
<p class=MsoBodyText style='margin-top:.35pt'><i style='mso-bidi-font-style:
normal'><span style='font-size:13.5pt;mso-bidi-font-size:11.0pt'><o:p> </o:p></span></i></p>
<h5 style='margin-left:61.0pt'><a name = "Alexander_City"></a><a name = "_bookmark3"></a><span
style='color:#FF2500'>Alexander City</span></h5>
<p class=MsoBodyText style='margin-top:.4pt'><b style='mso-bidi-font-weight:
normal'><i style='mso-bidi-font-style:normal'><span style='font-size:12.5pt;
mso-bidi-font-size:11.0pt'><o:p> </o:p></span></i></b></p>
<p class=MsoNormal style='margin-top:0in;margin-right:34.05pt;margin-bottom:
0in;margin-left:61.0pt;margin-bottom:.0001pt;line-height:100%'><b
style='mso-bidi-font-weight:normal'><span style='font-size:14.0pt;mso-bidi-font-size:
11.0pt;line-height:100%'>Alexander City Jazz Festival </span></b><a
href = "http://www.alexcityjazzfest.com/get-involved.html256-397-1019"><span
style='font-size:12.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>http://www.alexcityjazzfest.com/get-</span></a><span
style='font-size:12.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>
</span><a href = "http://www.alexcityjazzfest.com/get-involved.html256-397-1019"><span
style='font-size:12.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>involved.html256-397-1019</span></a><span
style='font-size:12.0pt;mso-bidi-font-size:11.0pt;line-height:100%;color:blue'>
</span><a href = "mailto:[email protected]"><span style='color:blue'>[email protected]</span></a></p>
<p class=MsoNormal style='margin-left:61.0pt;line-height:13.65pt;mso-line-height-rule:
exactly'><b style='mso-bidi-font-weight:normal'><i style='mso-bidi-font-style:
normal'><span style='font-size:12.0pt;mso-bidi-font-size:11.0pt'>Note: </span></i></b><i
style='mso-bidi-font-style:normal'><span style='font-size:12.0pt;mso-bidi-font-size:
11.0pt'>Online submission.<o:p></o:p></span></i></p>
<p class=MsoBodyText style='margin-top:.3pt;margin-right:0in;margin-bottom:
0in;margin-left:61.0pt;margin-bottom:.0001pt'>Festival Month(s): <i
style='mso-bidi-font-style:normal'>June<o:p></o:p></i></p>
import re
from re import search
import json
from collections import defaultdict
import os
f = open("./data/fairs-and-festivals-min.htm", "r", encoding = "utf-8")
# Variables ...
cityList = {}
festivalList = {
"festivals": []
}
file_pos = 0
for line in f:
# [0] Prepare dictionary for festival data ...
festivalBlock = {
"city": "",
"festivals": []
}
# [1] Find City w/ red text ...
cityData = re.search(r"'color:(#FF2500)'", line)
# Match was found ...
if (cityData):
# [2] Add city name to list ...
# Strip extra HTML from city name ...
city = re.findall(r"style='color:#FF2500'>(.*?)</span>", line)
city = " ".join(city) # Convert city from list to string ...
festivalBlock["city"] = city
# if cityData.group(1) not in cityList:
# cityList[cityData.group(1)] = [city]
# else:
# cityList[cityData.group(1)].append(city)
"""
Festival Blocks - DATA STRUCTURE:
"state": "Arizona",
"city": "Alabaster",
"festivals": [
{
"festival_name": "Hopkins Raspberry Festival",
"contact_name": "Lou Jean Gleason",
"contact_email": "[email protected]",
"contact_phone": "952-931-0878",
"notes": "Note: Online submission.",
"festival_months": "Festival Month(s): July"
},
{
"festival_name": "Hopkins Raspberry Festival",
"contact_name": "Lou Jean Gleason",
"contact_email": "[email protected]",
"contact_phone": "952-931-0878",
"notes": "Note: Online submission.",
"festival_months": "Festival Month(s): July"
}
]
"""
# [3] Find first festival in this city ...
# TODO: Look for multiple festivals within cities ...
# Get Festival name (span or h6) | STOP AFTER FIRST MATCH ...
festivalCount = 0 # iterator
for cityLine in f:
""" DEBUGGING CODE BELOW ... """
# if (festivalCount >= 3):
# continue
# Span version | Pattern 'line-height:xxx%'>festival_name</span>'
festivalName = re.findall(r"line-height:([+-]?([0-9]*[.])?[0-9]+)%'>(.*?)</span>", cityLine)
if (festivalName):
festival = defaultdict(list)
festival["festival_name"] = festivalName[0][2]
festivalBlock["festivals"].append(festival)
festivalCount += 1
break
else:
regex = re.compile(r">(.*?)</h6>", re.DOTALL)
festivalName = regex.findall(cityLine)
if (festivalName): # Festival name wrapped in h6 | Ignore empty strings
print(festivalName)
unwantedPhrase = "Note"
if not unwantedPhrase in festivalName:
# if unwantedPhrase in festivalName: # Ignore unwanted text/phrases (i.e. Note:)
festival = defaultdict(list)
festival["festival_name"] = festivalName
festivalBlock["festivals"].append(festival)
festivalCount += 1
break
break
# [4] Append block to list of festivals ...
festivalList["festivals"].append([festivalBlock])
# [Z] Iterate file line position...
file_pos += len(line)
else:
# [Z] Iterate file line position...
file_pos += len(line)
continue
# Print festivals to json file
output = open("./data/festivals.json", "w")
output.write(json.dumps(festivalList))
output.close()
Помимо Python, я пробовал украшение HTML-документ, минификация HTML-документ и даже использование jQuery.
Я пробовал библиотеки, такие как Py2PDF, PyQuery и html2str, но регулярные выражения кажутся наиболее практичным решением; учитывая, как плохо отформатирован HTML-документ.
Как я могу гарантировать, что мои методы регулярного выражения не пропускают элементы HTML, выходящие за пределы одной строки?
@TimBiegeleisen, спасибо! Будет ли он анализировать CSS и / или атрибуты? В HTML-документе нет согласованных классов или идентификаторов, поэтому я должен полагаться на встроенные стили как на отличия.
Он возвращает вам атрибуты. Вам решать, что делать со значениями атрибутов.
Совет дня: используйте библиотеку Beautiful Soup, регулярное выражение нет, для анализа содержимого HTML.