fix: extrai parágrafos de resumo estruturado (sec por subseção) - #1333
fix: extrai parágrafos de resumo estruturado (sec por subseção)#1333Rossi-Luciano wants to merge 1 commit into
Conversation
Corrige a issue scieloorg#1332: extract_abstract_data e extract_trans_abstract_data usavam node.findall('p'), que so acha <p> filho DIRETO de <abstract>/ <trans-abstract>. Um resumo estruturado (subsecoes tipo Introduction/ Methods/Results, cada uma sua propria <sec><title>...</title><p>...</p> </sec>) tem os <p> um nivel mais fundo, entao a extracao retornava content vazio - o PDF mostrava so o cabecalho "ABSTRACT"/"RESUMO" e ia direto pra "Keywords", sem nenhum texto de resumo. Adiciona _extract_abstract_paragraphs(node), helper recursivo que percorre <p> e <sec> em qualquer profundidade, incluindo o <title> de cada <sec> como rotulo (ja vem com o ":" da propria fonte, ex.: "Methods:"), preservando a estrutura do resumo em vez de so concatenar tudo. Reaproveitado nas duas funcoes, que tinham o mesmo bug. Confirmado contra o corpus real de 26 artigos: 6 (23%) tinham resumo vazio por esse motivo (a10, a11, a14, a17, a20, a28) - a10 tinha o RESUMO em portugues vazio tambem. Todos os 6 corrigidos; os outros 20 (resumo simples, sem <sec>) continuam identicos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X8r2LRJ3PGTT9vLaPtb373
| # Private helpers | ||
| # ----------------- | ||
|
|
||
| def _extract_abstract_paragraphs(node): |
| if p is not None: | ||
| abstract.append(''.join(p.itertext()).strip()) | ||
| data['content'] = ' '.join(abstract) | ||
| data['content'] = ' '.join(_extract_abstract_paragraphs(node_abstract)) |
There was a problem hiding this comment.
A extração agora preenche corretamente o resumo estruturado, mas no a10, por exemplo, esse mesmo conteúdo também entra novamente pelo extract_body_data(), que percorre xml_tree.findall('.//sec') e, portanto, inclui as de e . No resultado, “Background: A staggering 99%…” e “Contexto: Um número impressionante…” aparecem no resumo e outra vez como corpo. Precisamos restringir a extração do corpo às seções do principal. Veja como ficou:
Página 1:
Página 2:
Página 3:
pitangainnovare
left a comment
There was a problem hiding this comment.
A correção preenche os resumos estruturados que antes ficavam vazios, mas encontrei dois problemas na saída final que precisam ser tratados antes da aprovação.
No a10.xml, o conteúdo do ABSTRACT e do RESUMO passa a aparecer duas vezes. O PR agora extrai corretamente as <sec> internas do <abstract> e do <trans-abstract>, mas extract_body_data() continua usando xml_tree.findall('.//sec'). Com isso, ela também considera como corpo as seções pertencentes aos resumos.
No DOCX gerado pelo HEAD deste PR, por exemplo, “Background: A staggering 99%…” aparece uma vez no ABSTRACT e novamente como seção do corpo. O mesmo ocorre com “Contexto: Um número impressionante…” no RESUMO, além das demais seções Objective/Objetivo, Methods/Métodos, Results/Resultados e Conclusion/Conclusão.
Acredito que extract_body_data() deva percorrer somente as <sec> do <body> principal.
Também há um problema dos títulos de seções sem pontuação. A implementação pressupõe que todo <sec><title> já possui dois-pontos, mas isso não ocorre em parte do corpus. Em a11.xml, por exemplo, o XML contém <title>Objetivo</title>, e a saída fica “Objetivo descrever...”, enquanto o PDF publicado apresenta “Objetivo: descrever...”. O mesmo padrão aparece também em a17.xml e a20.xml. A formatação poderia, como solução, acrescentar um separador quando o título não trouxer pontuação final, sem duplicá-lo quando o XML já tiver :.
O que esse PR faz?
Corrige a issue #1332: quando um artigo tem resumo estruturado (subseções tipo Introduction/Methods/Results, cada uma dentro de sua própria
<sec>), o resumo saía vazio no PDF gerado — só o cabeçalho "ABSTRACT"/"RESUMO" aparecia, indo direto para "Keywords".extract_abstract_dataeextract_trans_abstract_data(packtools/sps/formats/pdf/pipeline/xml.py) usavamnode.findall('p'), que só localiza<p>filho direto do elemento<abstract>/<trans-abstract>. Num resumo estruturado, os<p>ficam um nível mais fundo (dentro de<sec>), então a extração retornava lista vazia.Adiciona
_extract_abstract_paragraphs(node), um helper recursivo que percorre<p>e<sec>em qualquer profundidade, incluindo o<title>de cada<sec>como rótulo (o texto fonte já vem com o:, ex."Methods:") — preserva a estrutura do resumo no texto final em vez de apagar a divisão entre subseções. Reaproveitado nas duas funções, que tinham exatamente o mesmo bug.Onde a revisão poderia começar?
packtools/sps/formats/pdf/pipeline/xml.py—_extract_abstract_paragraphs(helpers privados) e os dois pontos que passaram a chamá-la:extract_abstract_dataeextract_trans_abstract_data.Como este poderia ser testado manualmente?
Conferir o RESUMO/ABSTRACT na página 1.
Algum cenário de contexto que queira dar?
Achado por acaso revisando visualmente o corpus de teste de 26 artigos reais (
layout_examples_rafael/corpus/), enquanto validava outro fix (afiliação duplicada). Confirmei a causa raiz e a abrangência antes de abrir a issue #1332: 6 de 26 artigos (23%) tinham resumo vazio por esse motivo —a10.xml(RESUMO em português também vazio),a11.xml,a14.xml,a17.xml,a20.xml,a28.xml. Não é um caso raro nem exclusivo de uma área (saúde e administração/negócios ambos afetados).Screenshots
Quais são os tickets relevantes?
Corrige #1332.
Referências
N/A
Segurança da informação (NSI.04)
Este PR manipula dados sensíveis ou pessoais (LGPD)?
Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?
Este PR introduz, atualiza ou remove dependências de terceiros?
Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?
Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?
Este PR expõe novos endpoints, telas ou serviços?
Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?
🤖 Generated with Claude Code
https://claude.ai/code/session_01X8r2LRJ3PGTT9vLaPtb373