Skip to content

Instantly share code, notes, and snippets.

@me-suzy
Last active May 5, 2025 06:54
Show Gist options
  • Save me-suzy/d176519ce36cfed5f9ed93fd6be48f32 to your computer and use it in GitHub Desktop.
Save me-suzy/d176519ce36cfed5f9ed93fd6be48f32 to your computer and use it in GitHub Desktop.
categorii - verifica structura
import os
import re
from bs4 import BeautifulSoup, Tag, NavigableString
# Directoarele care trebuie verificate (doar folderele principale, fără subfoldere)
directories = [
r'e:\Carte\BB\17 - Site Leadership\Principal\ro',
r'e:\Carte\BB\17 - Site Leadership\Principal\en'
]
# Fișiere de ignorat
files_to_skip = [
r'e:\Carte\BB\17 - Site Leadership\Principal\en\python-scripts-examples.html',
r'e:\Carte\BB\17 - Site Leadership\Principal\ro\python-scripts-examples.html'
]
def extract_sections(html_content):
"""Extrage secțiunile dintre marcajele specificate."""
pattern = r'<!-- ARTICOL CATEGORIE START -->(.*?)<!-- ARTICOL CATEGORIE FINAL -->'
return re.findall(pattern, html_content, re.DOTALL)
def check_tag_attributes(tag):
"""Verifică dacă atributele unui tag HTML conțin caractere nevalide."""
errors = []
for attr_name, attr_value in tag.attrs.items():
# Verifică atribute cu caractere nevalide (de ex. {}, [], etc.)
if isinstance(attr_value, str):
if re.search(r'[{}\[\]]', attr_value):
errors.append(f"Atributul '{attr_name}' conține caractere nevalide: '{attr_value}'")
# Verifică dacă numele atributului conține caractere nevalide
if re.search(r'[{}\[\]]', attr_name):
errors.append(f"Numele atributului conține caractere nevalide: '{attr_name}'")
# Verifică dacă există text în tag-ul HTML care conține "{"
if tag.string and '{' in tag.string:
errors.append(f"Textul tag-ului conține caractere nevalide: '{tag.string}'")
return errors
def check_invalid_html_tags(html_content):
"""Verifică taguri HTML nevalide în conținutul HTML."""
# Lista de taguri HTML valide comune
valid_tags = ['html', 'head', 'body', 'div', 'span', 'p', 'a', 'img', 'table', 'tr', 'td', 'th',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'form', 'input', 'button',
'select', 'option', 'textarea', 'label', 'iframe', 'br', 'hr', 'em', 'strong', 'i', 'b',
'u', 'code', 'pre', 'blockquote', 'center', 'dl', 'dt', 'dd', 'fieldset', 'legend',
'font', 'style', 'script', 'meta', 'link', 'title', 'header', 'footer', 'nav', 'section',
'article', 'aside', 'main', 'figure', 'figcaption']
errors = []
# Găsește URL-ul primului articol pentru o identificare mai bună
soup = BeautifulSoup(html_content, 'html.parser')
article_url = None
first_table = soup.find('table')
if first_table:
den_articol = first_table.find('span', class_='den_articol')
if den_articol:
link = den_articol.find('a', class_='linkMare')
if link and link.get('href'):
article_url = link.get('href')
# Împărțim conținutul în linii pentru a putea raporta numărul liniei
lines = html_content.split('\n')
# Caută toate tagurile folosind expresii regulate pentru fiecare linie
for line_num, line in enumerate(lines, 1):
# Caută taguri deschise
tags = re.findall(r'<([a-zA-Z0-9]+)(?:\s+[^>]*)?>', line)
for tag in tags:
tag_lower = tag.lower()
if tag_lower not in valid_tags:
# Obținem contextul (text din jurul tag-ului)
pattern = r'(.{0,20})<' + re.escape(tag) + r'(?:\s+[^>]*)?>' + r'(.{0,20})'
context_match = re.search(pattern, line)
context = ""
if context_match:
before = context_match.group(1)
after = context_match.group(2)
context = f"{before}<{tag}>{after}"
error_msg = f"Tag HTML nevalid: <{tag}> la linia {line_num}, context: \"...{context}...\""
if article_url:
error_msg += f", înainte de articolul {article_url}"
errors.append(error_msg)
return errors
def check_table_structure_with_location(table, table_path=""):
"""Verifică structura internă a unui tabel pentru a detecta elemente nevalide cu locație."""
errors = []
# Stabilim calea pentru tabel
table_path = table_path if table_path else "table"
# Verifică dacă există elemente nevalide în interiorul tabelului
for child in table.children:
if isinstance(child, NavigableString) and child.strip():
# Am găsit text neașteptat direct în tabel
errors.append(f"Text neașteptat '{child.strip()}' găsit direct în elementul <{table_path}>")
elif isinstance(child, Tag) and child.name != 'tr':
# Am găsit un tag neașteptat direct în tabel
errors.append(f"Element neașteptat <{child.name}> găsit direct în elementul <{table_path}>")
# Verifică fiecare rând (tr) al tabelului
for tr_idx, tr in enumerate(table.find_all('tr', recursive=False), 1):
tr_path = f"{table_path}/tr[{tr_idx}]"
# Verifică dacă există elemente nevalide între rânduri
next_sibling = tr.next_sibling
while next_sibling and next_sibling.name != 'tr':
if isinstance(next_sibling, NavigableString) and next_sibling.strip():
errors.append(f"Text neașteptat '{next_sibling.strip()}' găsit între tag-urile </tr> și <tr> în {table_path}")
elif isinstance(next_sibling, Tag):
errors.append(f"Element neașteptat <{next_sibling.name}> găsit între tag-urile </tr> și <tr> în {table_path}")
next_sibling = next_sibling.next_sibling
# Verifică conținutul rândului
for child in tr.children:
if isinstance(child, NavigableString) and child.strip():
errors.append(f"Text neașteptat '{child.strip()}' găsit direct în tag-ul <{tr_path}>")
elif isinstance(child, Tag) and child.name != 'td' and child.name != 'th':
errors.append(f"Element neașteptat <{child.name}> găsit direct în tag-ul <{tr_path}>")
return errors
def check_element_problems(element, parent_path=""):
"""Verifică probleme de structură și tag-uri în elementele HTML."""
errors = []
current_path = parent_path
if isinstance(element, Tag):
current_path = f"{parent_path}/{element.name}" if parent_path else element.name
# Verifică dacă există atribute nevalide în elementul curent
for attr_name, attr_value in element.attrs.items():
if re.search(r'[{}\[\]<>]', str(attr_value)):
errors.append(f"Atribut invalid '{attr_name}=\"{attr_value}\"' în elementul <{current_path}>")
# Verifică dacă există copii nevalizi în elementul curent
for child in element.children:
if isinstance(child, NavigableString) and child.strip():
# Verifică text problematic
if "PROBLEMA" in child:
errors.append(f"Text problematic '{child.strip()}' găsit în <{current_path}>")
# Verifică dacă există text neașteptat în anumite elemente container
if element.name in ['table', 'tr', 'ul', 'ol'] and child.strip():
errors.append(f"Text neașteptat '{child.strip()}' găsit direct în elementul <{current_path}>")
# Verifică recursiv copiii
if isinstance(child, Tag):
child_errors = check_element_problems(child, current_path)
errors.extend(child_errors)
return errors
def check_invalid_attributes_in_html(tag):
"""Verifică tag-ul și toate tag-urile copil pentru atribute nevalide."""
errors = []
# Verifică atributele tag-ului curent
tag_errors = check_tag_attributes(tag)
if tag_errors:
errors.append(f"Tag-ul <{tag.name}> conține atribute nevalide: {', '.join(tag_errors)}")
# Verifică recursiv toate tag-urile copil
for child in tag.find_all(True, recursive=True):
child_errors = check_tag_attributes(child)
if child_errors:
errors.append(f"Tag-ul <{child.name}> conține atribute nevalide: {', '.join(child_errors)}")
return errors
def check_table_structure(table):
"""Verifică structura internă a unui tabel pentru a detecta elemente nevalide."""
errors = []
# Verifică atribute nevalide în tabel și tag-uri copil
attr_errors = check_invalid_attributes_in_html(table)
errors.extend(attr_errors)
# Verifică dacă există elemente nevalide în interiorul tabelului
for child in table.children:
if isinstance(child, NavigableString) and child.strip():
# Am găsit text neașteptat direct în tabel
errors.append(f"Text neașteptat '{child.strip()}' găsit direct în elementul <table>")
elif isinstance(child, Tag) and child.name != 'tr':
# Am găsit un tag neașteptat direct în tabel
errors.append(f"Element neașteptat <{child.name}> găsit direct în elementul <table>")
# Verifică fiecare rând (tr) al tabelului
for tr in table.find_all('tr', recursive=False):
# Verifică dacă există elemente nevalide între rânduri
next_sibling = tr.next_sibling
while next_sibling and next_sibling.name != 'tr':
if isinstance(next_sibling, NavigableString) and next_sibling.strip():
errors.append(f"Text neașteptat '{next_sibling.strip()}' găsit între tag-urile </tr> și <tr>")
elif isinstance(next_sibling, Tag):
errors.append(f"Element neașteptat <{next_sibling.name}> găsit între tag-urile </tr> și <tr>")
next_sibling = next_sibling.next_sibling
# Verifică conținutul rândului
for child in tr.children:
if isinstance(child, NavigableString) and child.strip():
errors.append(f"Text neașteptat '{child.strip()}' găsit direct în tag-ul <tr>")
elif isinstance(child, Tag) and child.name != 'td' and child.name != 'th':
errors.append(f"Element neașteptat <{child.name}> găsit direct în tag-ul <tr>")
# Verifică celulele (td/th) din rând
for cell in tr.find_all(['td', 'th'], recursive=False):
# Verifică atribute nevalide în celule
attr_errors = check_tag_attributes(cell)
if attr_errors:
errors.append(f"Tag-ul <{cell.name}> conține atribute nevalide: {', '.join(attr_errors)}")
# Verifică conținutul celulelor pentru probleme
for content in cell.contents:
if isinstance(content, NavigableString) and "PROBLEMA" in content:
errors.append(f"Text problematic '{content.strip()}' găsit în <{cell.name}>")
return errors
def identify_articles(soup):
"""Identifică articolele bazate pe șablonul corect."""
articles = []
current_article = []
# Găsește toate tabelele potențiale de header
tables = soup.find_all('table')
for table in tables:
# Verifică dacă tabelul are span class="den_articol"
if table.find('span', class_='den_articol'):
# Dacă avem un articol în construcție, îl finalizăm
if current_article:
articles.append(current_article)
current_article = []
# Începem un nou articol cu acest tabel
current_article.append(table)
# Găsește următoarele elemente ale articolului
current_element = table.find_next_sibling()
# Adaugă elementele până la următorul tabel cu den_articol sau sfârșitul secțiunii
while current_element:
# Dacă am găsit un nou tabel de header, oprim acest articol
if current_element.name == 'table' and current_element.find('span', class_='den_articol'):
break
current_article.append(current_element)
current_element = current_element.find_next_sibling()
# Adaugă ultimul articol dacă există
if current_article:
articles.append(current_article)
return articles
def get_article_title(article_elements):
"""Extrage titlul articolului din elementele articolului."""
if not article_elements:
return "Articol fără elemente"
header_table = article_elements[0]
den_articol = header_table.find('span', class_='den_articol')
if not den_articol:
return "Articol fără titlu"
link = den_articol.find('a', class_='linkMare')
if link and link.string:
return link.string.strip()
elif link and link.get_text():
return link.get_text().strip()
elif den_articol.get_text():
return den_articol.get_text().strip()
return "Articol cu titlu nedetectabil"
def get_article_url(article_elements):
"""Extrage URL-ul articolului din elementele articolului."""
if not article_elements:
return None
header_table = article_elements[0]
den_articol = header_table.find('span', class_='den_articol')
if not den_articol:
return None
link = den_articol.find('a', class_='linkMare')
if link and link.get('href'):
return link.get('href')
return None
def check_a_tag_problems(tag):
"""Verifică tag-urile <a> pentru probleme specifice."""
errors = []
# Verifică toate tag-urile <a> din elementul dat
for a_tag in tag.find_all('a'):
# Verifică dacă există un tag <a> fără închidere corectă
if a_tag.get('href') and not a_tag.get('href').startswith('http'):
# Verifică atributele href pentru a detecta probleme
href_attr = a_tag.attrs.get('href', '')
# Verifică dacă există spații între atribute
tag_str = str(a_tag)
if ' href=' not in tag_str and 'href=' in tag_str:
errors.append(f"Tag-ul <a> nu are spațiu înainte de atributul href: {tag_str}")
# Verifică dacă există ghilimele lipsă
if re.search(r'href=([^"\'])', tag_str):
errors.append(f"Atributul href nu are ghilimele: {tag_str}")
return errors
def check_between_articles(articles, idx):
"""Identifică și descrie elementele între articole."""
if idx >= len(articles) - 1:
return [] # Nu există articol următor
current_article = articles[idx]
next_article = articles[idx+1]
# Obținem URL-urile pentru identificare
current_url = get_article_url(current_article)
next_url = get_article_url(next_article)
# Verificăm dacă primul element al articolului următor vine direct după ultimul element al articolului curent
last_elem = current_article[-1]
if last_elem and last_elem.name == 'p' and last_elem.get('class') and 'text_obisnuit' in last_elem.get('class'):
next_elem = last_elem.find_next_sibling()
if next_elem and next_elem != next_article[0]:
# Colectează toate elementele între articole
between_elements = []
while next_elem and next_elem != next_article[0]:
between_elements.append(next_elem)
next_elem = next_elem.find_next_sibling()
if between_elements:
error_msg = []
# Formatăm elementele găsite într-un mod mai clar
html_elements = []
for elem in between_elements:
if isinstance(elem, Tag):
if elem.name == 'br':
html_elements.append("<br>")
elif elem.name == 'table':
html_elements.append("<table...>")
elif elem.name == 'div':
align = elem.get('align', '')
html_elements.append(f"<div align=\"{align}\">")
else:
html_elements.append(f"<{elem.name}>")
else:
# Element text
text = str(elem).strip()
if text:
html_elements.append(text[:30] + "..." if len(text) > 30 else text)
# Grupăm elementele identice consecutive
grouped_elements = []
last_elem = None
count = 0
for html_elem in html_elements:
if html_elem == last_elem:
count += 1
else:
if count > 1:
grouped_elements.append(f"{last_elem} (repetat de {count} ori)")
elif count == 1:
grouped_elements.append(last_elem)
last_elem = html_elem
count = 1
# Adăugăm ultimul grup
if count > 1:
grouped_elements.append(f"{last_elem} (repetat de {count} ori)")
elif count == 1:
grouped_elements.append(last_elem)
if grouped_elements:
elements_str = ", ".join(grouped_elements)
error_msg.append(f"S-au găsit elemente suplimentare între articolul cu URL {current_url} și articolul cu URL {next_url}: {elements_str}")
return error_msg
return []
def get_element_html_string(element):
"""Returnează reprezentarea HTML ca string pentru un element."""
if isinstance(element, Tag):
tag_name = element.name
attrs = []
for attr, value in element.attrs.items():
if isinstance(value, list):
value = " ".join(value)
attrs.append(f'{attr}="{value}"')
attrs_str = " ".join(attrs)
if attrs_str:
return f"<{tag_name} {attrs_str}>"
return f"<{tag_name}>"
else:
return str(element)
def check_article_structure(article_elements, all_articles, article_index):
"""Verifică structura unui articol."""
errors = []
# Verifică tabelul header (primul element)
if not article_elements or article_elements[0].name != 'table':
return ["Articolul nu începe cu un tabel header"]
header_table = article_elements[0]
# Obține titlul și URL-ul articolului pentru referință
title = get_article_title(article_elements)
url = get_article_url(article_elements)
# Verifică fiecare element din articol pentru text neașteptat
for i, element in enumerate(article_elements):
if isinstance(element, Tag):
# Verifică textul direct în element (inclusiv între tag-uri)
for j, content in enumerate(element.contents):
if isinstance(content, NavigableString) and content.strip():
errors.append(f"Text neașteptat '{content.strip()}' găsit în elementul <{element.name}> din articolul \"{title}\"")
# Verifică atribute nevalide și alte probleme
attr_errors = check_invalid_attributes_in_html(element)
if attr_errors:
errors.extend(attr_errors)
# Verifică tag-urile <a> pentru probleme
a_tag_errors = check_a_tag_problems(element)
if a_tag_errors:
errors.extend(a_tag_errors)
# Verifică tag-uri neașteptate între elemente consecutive
if i < len(article_elements) - 1:
# Găsim elementul următor
next_elem = article_elements[i+1]
# Verificăm dacă există text între elementul curent și cel următor
current_next_sibling = element.next_sibling
while current_next_sibling and current_next_sibling != next_elem:
if isinstance(current_next_sibling, NavigableString) and current_next_sibling.strip():
errors.append(f"Text neașteptat '{current_next_sibling.strip()}' găsit între <{element.name}> și <{next_elem.name}> în articolul \"{title}\"")
current_next_sibling = current_next_sibling.next_sibling
# Verifică text problematic în interiorul elementelor
for element in article_elements:
if isinstance(element, Tag):
for text in element.find_all(text=True):
if "PROBLEMA" in text:
errors.append(f"Text problematic '{text.strip()}' găsit în <{element.name}>")
# Verifică structura internă a tabelului header
table_structure_errors = check_table_structure(header_table)
if table_structure_errors:
errors.extend(table_structure_errors)
# Verifică span class="den_articol"
den_articol = header_table.find('span', class_='den_articol')
if not den_articol:
errors.append("Tabelul header nu conține span class='den_articol'")
else:
# Verifică link cu class="linkMare"
link_mare = den_articol.find('a', class_='linkMare')
if not link_mare:
errors.append("Span-ul den_articol nu conține link cu class='linkMare'")
else:
# Verifică atribute nevalide în link-ul mare
link_attr_errors = check_tag_attributes(link_mare)
if link_attr_errors:
errors.append(f"Link-ul cu class='linkMare' conține atribute nevalide: {', '.join(link_attr_errors)}")
# Verifică td class="text_dreapta"
text_dreapta = header_table.find('td', class_='text_dreapta')
if not text_dreapta:
errors.append("Tabelul header nu conține td class='text_dreapta' pentru dată și categorie")
# Verifică paragraful descriptiv
if len(article_elements) < 2 or article_elements[1].name != 'p' or not article_elements[1].get('class') or 'text_obisnuit2' not in article_elements[1].get('class'):
errors.append("Lipsește paragraful descriptiv <p class='text_obisnuit2'>")
else:
# Verifică text italic
em_tag = article_elements[1].find('em')
if not em_tag:
errors.append("Paragraful descriptiv nu conține text italic <em>")
# Verifică tabelul de "read more"/"citește mai departe"
read_more_table_index = -1
for i, elem in enumerate(article_elements):
if i >= 2 and elem.name == 'table' and elem.find('div', id='external2'):
read_more_table_index = i
break
if read_more_table_index == -1:
errors.append("Lipsește tabelul cu div id='external2' pentru 'citește mai departe'")
else:
read_more_table = article_elements[read_more_table_index]
# Verifică structura internă a tabelului read_more
table_structure_errors = check_table_structure(read_more_table)
if table_structure_errors:
errors.extend(table_structure_errors)
external2_div = read_more_table.find('div', id='external2')
if external2_div.get('align') != 'right':
errors.append("Div-ul external2 nu are align='right'")
# Verifică atribute invalide în div-ul external2
div_attr_errors = check_tag_attributes(external2_div)
if div_attr_errors:
errors.append(f"Div-ul external2 conține atribute nevalide: {', '.join(div_attr_errors)}")
# Verifică specific pentru text după tabelul "citește mai departe" și înainte de paragraful final
if read_more_table_index != -1 and read_more_table_index + 1 < len(article_elements):
read_more_table = article_elements[read_more_table_index]
next_elem = article_elements[read_more_table_index + 1]
# Verifică text între tabelul "citește mai departe" și elementul următor
current = read_more_table.next_sibling
while current and current != next_elem:
if isinstance(current, NavigableString) and current.strip():
errors.append(f"Text neașteptat '{current.strip()}' găsit după tabelul 'citește mai departe' în articolul \"{title}\"")
current = current.next_sibling
# Verifică paragraful gol final
has_final_p = False
has_wrong_final_p = False
final_p_issues = []
unexpected_elements = []
# Căutăm elementele după tabelul de "citește mai departe"
if read_more_table_index != -1 and read_more_table_index + 1 < len(article_elements):
# Verificăm toate elementele după tabelul de "citește mai departe"
for i in range(read_more_table_index + 1, len(article_elements)):
elem = article_elements[i]
# Verifică dacă este paragraf final corect
if elem.name == 'p' and elem.get('class') and 'text_obisnuit' in elem.get('class'):
if len(elem.get('class')) == 1 and not elem.get('align') and not elem.string:
# Paragraf corect
has_final_p = True
else:
# Paragraf incorect (atribute suplimentare sau text)
has_wrong_final_p = True
attrs = []
for attr, value in elem.attrs.items():
if isinstance(value, list):
value = " ".join(value)
attrs.append(f'{attr}="{value}"')
attrs_str = " ".join(attrs)
final_p_issues.append(f"Există un paragraf final incorect: <p {attrs_str}> în loc de <p class=\"text_obisnuit\"></p>")
# Verifică dacă sunt paragrafe finale repetate
elif has_final_p and elem.name == 'p' and elem.get('class') and 'text_obisnuit' in elem.get('class'):
final_p_issues.append("Paragrafele <p class=\"text_obisnuit\"></p> se repetă unul după altul")
# Detectează alte elemente neașteptate
elif not has_final_p:
unexpected_elements.append(elem)
# Procesează elementele neașteptate
if unexpected_elements:
# Grupează elementele consecutive de același tip
element_groups = []
current_group = []
current_type = None
for elem in unexpected_elements:
elem_type = elem.name if isinstance(elem, Tag) else type(elem).__name__
if elem_type == current_type:
current_group.append(elem)
else:
if current_group:
element_groups.append((current_type, current_group))
current_type = elem_type
current_group = [elem]
# Adaugă ultimul grup
if current_group:
element_groups.append((current_type, current_group))
# Raportează elementele grupate
for elem_type, group in element_groups:
if elem_type == 'br' and len(group) > 1:
# Grupează tag-urile <br> multiple
br_html = "<br>" * len(group)
final_p_issues.append(f"Elementul {br_html} este în plus între tagul </table> și <p class=\"text_obisnuit\"></p>")
elif len(group) > 1:
# Alte elemente repetate
elem_html = get_element_html_string(group[0])
final_p_issues.append(f"Elementul {elem_html} se repetă de {len(group)} ori între tagul </table> și <p class=\"text_obisnuit\"></p>")
else:
# Elemente individuale
elem_html = get_element_html_string(group[0])
final_p_issues.append(f"Elementul {elem_html} este în plus între tagul </table> și <p class=\"text_obisnuit\"></p>")
# Verifică dacă lipsește paragraful final
if not has_final_p and not has_wrong_final_p:
final_p_issues.append("Lipsește <p class=\"text_obisnuit\"></p> la sfârșitul articolului")
# Adaugă erorile de paragraf final la lista de erori
errors.extend(final_p_issues)
# Verifică dacă link-urile se repetă de mai mult de 2 ori
if den_articol and read_more_table_index != -1 and 'external2_div' in locals() and external2_div:
title_links = [a.get('href') for a in den_articol.find_all('a', href=True)]
read_more_links = [a.get('href') for a in external2_div.find_all('a', href=True) if not a.find('img')]
all_links = title_links + read_more_links
link_counts = {}
for link in all_links:
link_counts[link] = link_counts.get(link, 0) + 1
for link, count in link_counts.items():
if count > 2:
errors.append(f"Link-ul '{link}' apare de {count} ori (în loc de maxim 2)")
# Verifică elementele între articole
between_errors = check_between_articles(all_articles, article_index)
errors.extend(between_errors)
# Verifică text după ultimul element al articolului
if article_elements:
last_elem = article_elements[-1]
next_sibling = last_elem.next_sibling
while next_sibling:
if isinstance(next_sibling, NavigableString) and next_sibling.strip():
errors.append(f"Text neașteptat '{next_sibling.strip()}' găsit după ultimul element al articolului \"{title}\"")
elif isinstance(next_sibling, Tag):
# Dacă următorul element este un nou tabel header, am trecut la alt articol
if next_sibling.name == 'table' and next_sibling.find('span', class_='den_articol'):
break
next_sibling = next_sibling.next_sibling
return errors
def check_section_structure(section):
"""Verifică structura secțiunii pentru articolele corecte."""
soup = BeautifulSoup(section, 'html.parser')
errors = []
# Verifică taguri HTML nevalide în întreaga secțiune
invalid_tag_errors = check_invalid_html_tags(section)
if invalid_tag_errors:
errors.extend(invalid_tag_errors)
# Verifică dacă există text/elemente nevalide direct în secțiune (în afara articolelor)
for child in soup.children:
if isinstance(child, NavigableString) and child.strip() and not child.strip().startswith("<!--") and not child.strip().endswith("-->"):
# Text neașteptat în afara articolelor și care nu este comentariu HTML
errors.append(f"Text neașteptat găsit direct în secțiune: '{child.strip()}'")
elif isinstance(child, Tag):
# Verifică textul direct în elementele de nivel superior
for direct_text in child.contents:
if isinstance(direct_text, NavigableString) and direct_text.strip() and not direct_text.strip().startswith("<!--") and not direct_text.strip().endswith("-->"):
errors.append(f"Text neașteptat găsit în <{child.name}>: '{direct_text.strip()}'")
# Verifică dacă există text problematic în elementele de nivel superior
for text in child.find_all(text=True):
if "PROBLEMA" in text:
errors.append(f"Text problematic '{text.strip()}' găsit în <{child.name}>")
# Verifică text neașteptat oriunde în secțiune, nu doar la nivel superior
# Caută text în afara tag-urilor HTML în întregul document
for text in soup.find_all(text=True):
if text.strip() and not text.strip().startswith("<!--") and not text.strip().endswith("-->"):
# Verifică dacă textul este în interiorul unui element valid
parent = text.parent
# Dacă textul este direct în body, div align="justify", sau în alte locuri neașteptate
if (parent.name == 'body' or
(parent.name == 'div' and parent.get('align') == 'justify') or
parent.name in ['table', 'tr']):
# Evită raportarea textului din celule td/th, span, a, p - acestea sunt locuri valide pentru text
if not (parent.name in ['td', 'th', 'span', 'a', 'em', 'p']):
errors.append(f"Text neașteptat '{text.strip()}' găsit în <{parent.name}>")
# Specifică verificare pentru text după ultimul div al secțiunii
main_div = soup.find('div', attrs={'align': 'justify'})
if main_div:
next_sibling = main_div.next_sibling
while next_sibling:
if isinstance(next_sibling, NavigableString) and next_sibling.strip():
errors.append(f"Text neașteptat '{next_sibling.strip()}' găsit după tag-ul </div> în secțiune")
next_sibling = next_sibling.next_sibling
# Identifică articolele
articles = identify_articles(soup)
if not articles:
errors.append("Nu s-au găsit articole în secțiune")
return False, "\n".join(errors)
# Verifică fiecare articol
articles_with_errors = []
for idx, article_elements in enumerate(articles):
article_errors = check_article_structure(article_elements, articles, idx)
if article_errors:
title = get_article_title(article_elements)
url = get_article_url(article_elements)
articles_with_errors.append((idx+1, title, url, article_errors))
if articles_with_errors:
for article_idx, title, url, article_errors in articles_with_errors:
errors.append(f"Articolul {article_idx} - \"{title}\" (URL: {url}):")
for error in article_errors:
errors.append(f" - {error}")
if errors:
return False, "\n".join(errors)
return True, None
def read_file_with_multiple_encodings(file_path):
"""Încearcă să citească fișierul cu diferite codificări."""
encodings = ['utf-8', 'latin-1', 'cp1252', 'iso-8859-1']
for encoding in encodings:
try:
with open(file_path, 'r', encoding=encoding) as file:
return file.read()
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"Nu s-a putut citi fișierul {file_path} cu niciuna din codificările: {encodings}")
def check_file_structure(file_path):
"""Verifică structura unui fișier HTML."""
# Verifică dacă fișierul este în lista celor de ignorat
if file_path in files_to_skip:
print(f"[Ignorat] {file_path}")
return None
try:
content = read_file_with_multiple_encodings(file_path)
sections = extract_sections(content)
if not sections:
return None
# Colectează toate erorile brute
all_errors = []
for idx, section in enumerate(sections):
is_valid, error_msg = check_section_structure(section)
if not is_valid:
all_errors.append(f"Secțiunea {idx+1} conține erori de structură:")
# Împarte mesajul de eroare în linii și le adaugă cu formatare
for line in error_msg.split('\n'):
if line.strip():
# Filtrează erorile care se repetă
if not any(similar_error in all_errors for similar_error in get_similar_errors(line)):
# Îmbunătățește mesajele cu localizări clare
enhanced_line = enhance_error_location(line)
all_errors.append(f" {enhanced_line}")
if all_errors:
# Procesează lista finală pentru a elimina duplicatele
clean_errors = remove_duplicates(all_errors)
return (file_path, clean_errors)
return None
except Exception as e:
return (file_path, [f"Eroare la procesarea fișierului: {e}"])
def get_similar_errors(error):
"""Generează variante de erori similare pentru a detecta duplicatele."""
variants = []
# Creează variante pentru a detecta duplicatele
if "Text neașteptat" in error:
# Extrage textul problematic
text_match = re.search(r"Text neașteptat '([^']+)'", error)
if text_match:
text = text_match.group(1)
variants.append(f"Text neașteptat '{text}' găsit în")
variants.append(f"Text neașteptat '{text}' găsit direct în")
return variants
def enhance_error_location(error):
"""Îmbunătățește mesajul de eroare cu localizare clară."""
# Pentru text după div
if "găsit după tag-ul </div>" in error:
return error.replace("găsit după tag-ul </div> în secțiune",
"găsit între </div> și <!-- ARTICOL CATEGORIE FINAL -->")
# Pentru text în secțiune
if "găsit direct în secțiune" in error:
return error.replace("găsit direct în secțiune",
"găsit înainte de <div align=\"justify\">")
# Pentru text în tabele/rânduri fără context
if re.search(r"găsit (?:direct )?în (?:elementul )?<(table|tr|p)>", error) and "articolul" not in error:
# Identifică articolul din context pentru a adăuga la localizare
url_match = re.search(r"URL: (https://[^\s]+)", error)
if url_match:
url = url_match.group(1)
return error + f" (în articolul cu URL {url})"
return error
def remove_duplicates(errors):
"""Elimină duplicatele din lista de erori."""
unique_errors = []
seen = set()
for error in errors:
# Creează o cheie simplificată pentru a detecta duplicatele
key = re.sub(r"în articolul .*?$", "", error)
key = re.sub(r"la linia \d+", "", key)
key = re.sub(r"context: .*?$", "", key)
key = key.strip()
if key not in seen:
seen.add(key)
unique_errors.append(error)
return unique_errors
def check_html_string(html_content):
"""Verifică structura unui string HTML."""
sections = extract_sections(html_content)
if not sections:
return ["Nu s-au găsit secțiuni între marcajele <!-- ARTICOL CATEGORIE START --> și <!-- ARTICOL CATEGORIE FINAL -->"]
errors = []
for idx, section in enumerate(sections):
is_valid, error_msg = check_section_structure(section)
if not is_valid:
errors.append(f"Secțiunea {idx+1} conține erori de structură:\n{error_msg}")
return errors
def main():
files_with_issues = []
total_files = 0
processed_files = 0
skipped_files = 0
# Calculează numărul total de fișiere HTML din folderele principale (fără subfoldere)
for directory in directories:
files = [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))
and (f.lower().endswith('.html') or f.lower().endswith('.htm'))]
total_files += len(files)
print(f"Începe verificarea structurii pentru {total_files} fișiere HTML...")
# Procesează fișierele din folderele principale (fără subfoldere)
for directory in directories:
print(f"Scanez directorul: {directory}")
# Listează doar fișierele din directorul principal, fără subfoldere
files = [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))
and (f.lower().endswith('.html') or f.lower().endswith('.htm'))]
for file in files:
file_path = os.path.join(directory, file)
# Verifică dacă fișierul este în lista celor de ignorat
if file_path in files_to_skip:
skipped_files += 1
print(f"[{processed_files+skipped_files}/{total_files}] [Ignorat] {file}")
continue
processed_files += 1
print(f"[{processed_files+skipped_files}/{total_files}] {file}")
result = check_file_structure(file_path)
if result:
files_with_issues.append(result)
print("\n---- Rezultate finale ----")
if files_with_issues:
print(f"S-au găsit {len(files_with_issues)} fișiere cu structuri HTML neconforme:\n")
for i, (file_path, errors) in enumerate(files_with_issues):
print(f"{file_path}:")
for error in errors:
print(f" {error}")
# Adaugă linia de separare după fiecare fișier, exceptând ultimul
if i < len(files_with_issues) - 1:
print("-------")
else:
print("Nu s-au găsit fișiere cu structuri HTML neconforme.")
print(f"\nProcesare completă: {processed_files} fișiere verificate, {skipped_files} fișiere ignorate.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment