class_docstr: Makes text documents more readable by removing extra whitespaces, empty lines, specified substrings, regexes, page headers and footers (in this order).
  This is useful for preparing the documents for further processing by LLMs.
  
  Example usage in an indexing pipeline:
  
  ```python
  document_store = InMemoryDocumentStore()
  p = Pipeline()
  p.add_component(instance=TextFileToDocument(), name="text_file_converter")
  p.add_component(instance=DocumentCleaner(), name="cleaner")
  p.add_component(instance=TextDocumentSplitter(split_by="sentence", split_length=1), name="splitter")
  p.add_component(instance=DocumentWriter(document_store=document_store), name="writer")
  p.connect("text_file_converter.documents", "cleaner.documents")
  p.connect("cleaner.documents", "splitter.documents")
  p.connect("splitter.documents", "writer.documents")
  ```
class_docstr_tok: ["Makes","text","documents","more","readable","by","removing","extra","whitespaces",",","empty","lines",",","specified","substrings",",","regexes",",","page","headers","and","footers","(","in","this","order",")",".","This","is","useful","for","preparing","the","documents","for","further","processing","by","LLMs",".","Example","usage","in","an","indexing","pipeline",":","``","`","python","document_store","=","InMemoryDocumentStore","(",")","p","=","Pipeline","(",")","p.add_component","(","instance=TextFileToDocument","(",")",",","name=","''","text_file_converter","''",")","p.add_component","(","instance=DocumentCleaner","(",")",",","name=","''","cleaner","''",")","p.add_component","(","instance=TextDocumentSplitter","(","split_by=","''","sentence","''",",","split_length=1",")",",","name=","''","splitter","''",")","p.add_component","(","instance=DocumentWriter","(","document_store=document_store",")",",","name=","''","writer","''",")","p.connect","(","``","text_file_converter.documents","''",",","``","cleaner.documents","''",")","p.connect","(","``","cleaner.documents","''",",","``","splitter.documents","''",")","p.connect","(","``","splitter.documents","''",",","``","writer.documents","''",")","``","`"]
docstr: Heuristic to find footers and headers across different pages by searching for the longest common string.
  Pages in the text need to be separated by form feed character "".
  For headers, we only search in the first n_chars characters (for footer: last n_chars).
  Note: This heuristic uses exact matches and therefore works well for footers like "Copyright 2019 by XXX",
   but won't detect "Page 3 of 4" or similar.
  
  :param n_chars: The number of first/last characters where the header/footer shall be searched in.
  :param n_first_pages_to_ignore: The number of first pages to ignore (e.g. TOCs often don't contain footer/header).
  :param n_last_pages_to_ignore: The number of last pages to ignore.
  :return: The text without the found headers and footers.
docstr_tok: ["Heuristic","to","find","footers","and","headers","across","different","pages","by","searching","for","the","longest","common","string",".","Pages","in","the","text","need","to","be","separated","by","form","feed","character","``","''",".","For","headers",",","we","only","search","in","the","first","n_chars","characters","(","for","footer",":","last","n_chars",")",".","Note",":","This","heuristic","uses","exact","matches","and","therefore","works","well","for","footers","like","``","Copyright","2019","by","XXX","''",",","but","wo","n't","detect","``","Page","3","of","4","''","or","similar",".",":","param","n_chars",":","The","number","of","first\/last","characters","where","the","header\/footer","shall","be","searched","in",".",":","param","n_first_pages_to_ignore",":","The","number","of","first","pages","to","ignore","(","e.g",".","TOCs","often","do","n't","contain","footer\/header",")",".",":","param","n_last_pages_to_ignore",":","The","number","of","last","pages","to","ignore",".",":","return",":","The","text","without","the","found","headers","and","footers","."]
code: def _find_and_remove_header_footer(
      self,
      text: str,
      n_chars: int,
      n_first_pages_to_ignore: int,
      n_last_pages_to_ignore: int,
  ) -> str:
      """
      Heuristic to find footers and headers across different pages by searching for the longest common string.
      Pages in the text need to be separated by form feed character "\f".
      For headers, we only search in the first n_chars characters (for footer: last n_chars).
      Note: This heuristic uses exact matches and therefore works well for footers like "Copyright 2019 by XXX",
       but won't detect "Page 3 of 4" or similar.
  
      :param n_chars: The number of first/last characters where the header/footer shall be searched in.
      :param n_first_pages_to_ignore: The number of first pages to ignore (e.g. TOCs often don't contain footer/header).
      :param n_last_pages_to_ignore: The number of last pages to ignore.
      :return: The text without the found headers and footers.
      """
  
      pages = text.split("\f")
  
      # header
      start_of_pages = [
          p[:n_chars]
          for p in pages[
              n_first_pages_to_ignore:-n_last_pages_to_ignore
          ]
      ]
      found_header = self._find_longest_common_ngram(start_of_pages)
      if found_header:
          pages = [page.replace(found_header, "") for page in pages]
  
      # footer
      end_of_pages = [
          p[-n_chars:]
          for p in pages[
              n_first_pages_to_ignore:-n_last_pages_to_ignore
          ]
      ]
      found_footer = self._find_longest_common_ngram(end_of_pages)
      if found_footer:
          pages = [page.replace(found_footer, "") for page in pages]
  
      logger.debug(
          "Removed header '%s' and footer '%s' in document",
          found_header,
          found_footer,
      )
      text = "\f".join(pages)
      return text
  
file_path: haystack/haystack/components/preprocessors/document_cleaner.py
imports: import logging
  import re
  from copy import deepcopy
  from functools import partial, reduce
  from itertools import chain
  from typing import Generator, List, Optional, Set
  from haystack import Document, component
label_desc: Use image node_id 8 for calling the DocumentCleaner obj's underlying member method code with example usage: obj._find_and_remove_header_footer(text, n_chars, n_first_pages_to_ignore, n_last_pages_to_ignore) and returns: text