alan-turing-institute / ReadabiliPy

A simple HTML content extractor in Python. Can be run as a wrapper for Mozilla's Readability.js package or in pure-python mode.
MIT License
230 stars 36 forks source link

Make plain-content generation more robust #21

Closed jemrobinson closed 5 years ago

jemrobinson commented 5 years ago

New approach for plain content generation

The new approach will remove all html tags that are not in a specified whitelist of block-level elements, replacing most of the removed elements with their plain text content, but dropping some blacklisted elements completely (e.g. img, video, audio, script).

To do this we will implement the following algorithm:

  1. Start at the top-level "readability" div element we have wrapped the article HTML in.
  2. Navigate to the next "leaf" node (terminal child element) under the current element.
  3. Process the node: a. If the node is a Text element, keep it. b. If the node is not a Text element and is a blacklisted element, remove it c. If the node is not a Text element, is not a blacklisted element, and has special handling rules, apply these. d. If the node is not a Text element, is not a blacklisted element, and has no special handling rules replace it with the node's innerText. This is a representation of the layout with all styling removed. In our case, we will have ensured all children are text, so we can also just grab the textContent. Both of these are defined in the HTML standard. In practice, we will probably use Beautiful Soup's get_text(" ", strip=True) function, stripping training and leading whitespace from child Text elements before recombining them with a single space between them into a single Text element.
  4. Navigate to the node's parent.
  5. If the parent node is a blacklisted element, remove the node.
  6. If the parent node is a whitelisted element and the previously processed child node is both the only child node and a Text element, wrap this child Text element in a p paragraph element.
  7. If the parent has unprocessed children, goto step 2.
  8. If the parent has no unprocessed children, goto step 4.

Element lists

Block-level whitelist

article aside blockquote caption colgroup col div dl dt dd figure figcaption footer h1 h2 h3 h4 h5 h6 header li main ol p pre section table tbody thead tfoot tr td th ul

Blacklist for complete removal

These elements will be completely removed, along with all their children. Q: Should we replace these with a " content removed" placeholder? We were discussing doing this for MathML, though I've decided to treat this the same as other embedded content and just remove this for now.

Elements with special handling

Undecided

Remaining elements

These elements will be replaced with their innerText (concatenated text representations of all their children, with sensible whitespace rules for concatenation). a abbr address b bdi bdo cite code del dfn em i ins kbs mark q rb ruby rp rt rtc s samp small span strong u var wbr

Notes on classification of elements: