class_docstr: LinkContentFetcher is a component for fetching and extracting content from URLs. It supports handling various
  content types, retries on failures, and automatic user-agent rotation for failed web requests.
class_docstr_tok: ["LinkContentFetcher","is","a","component","for","fetching","and","extracting","content","from","URLs",".","It","supports","handling","various","content","types",",","retries","on","failures",",","and","automatic","user-agent","rotation","for","failed","web","requests","."]
docstr: Fetches content from a list of URLs and returns a list of extracted content streams.
  Each content stream is a ByteStream object containing the extracted content as binary data.
  Each ByteStream object in the returned list corresponds to the contents of a single URL.
  The content type of each stream is stored in the metadata of the ByteStream object under
  the key "content_type". The URL of the fetched content is stored under the key "url".
  
  :param urls: A list of URLs to fetch content from.
  :return: A lists of ByteStream objects representing the extracted content.
  
  :raises: If the provided list of URLs contains only a single URL, and `raise_on_failure` is set to True,
  an exception will be raised in case of an error during content retrieval. In all other scenarios, any
  retrieval errors are logged, and a list of successfully retrieved ByteStream objects is returned.
docstr_tok: ["Fetches","content","from","a","list","of","URLs","and","returns","a","list","of","extracted","content","streams",".","Each","content","stream","is","a","ByteStream","object","containing","the","extracted","content","as","binary","data",".","Each","ByteStream","object","in","the","returned","list","corresponds","to","the","contents","of","a","single","URL",".","The","content","type","of","each","stream","is","stored","in","the","metadata","of","the","ByteStream","object","under","the","key","``","content_type","''",".","The","URL","of","the","fetched","content","is","stored","under","the","key","``","url","''",".",":","param","urls",":","A","list","of","URLs","to","fetch","content","from",".",":","return",":","A","lists","of","ByteStream","objects","representing","the","extracted","content",".",":","raises",":","If","the","provided","list","of","URLs","contains","only","a","single","URL",",","and","`","raise_on_failure","`","is","set","to","True",",","an","exception","will","be","raised","in","case","of","an","error","during","content","retrieval",".","In","all","other","scenarios",",","any","retrieval","errors","are","logged",",","and","a","list","of","successfully","retrieved","ByteStream","objects","is","returned","."]
code: def run(self, urls: List[str]):
      """
      Fetches content from a list of URLs and returns a list of extracted content streams.
      Each content stream is a ByteStream object containing the extracted content as binary data.
      Each ByteStream object in the returned list corresponds to the contents of a single URL.
      The content type of each stream is stored in the metadata of the ByteStream object under
      the key "content_type". The URL of the fetched content is stored under the key "url".
  
      :param urls: A list of URLs to fetch content from.
      :return: A lists of ByteStream objects representing the extracted content.
  
      :raises: If the provided list of URLs contains only a single URL, and `raise_on_failure` is set to True,
      an exception will be raised in case of an error during content retrieval. In all other scenarios, any
      retrieval errors are logged, and a list of successfully retrieved ByteStream objects is returned.
      """
      streams: List[ByteStream] = []
      if not urls:
          return {"streams": streams}
  
      # don't use multithreading if there's only one URL
      if len(urls) == 1:
          stream_metadata, stream = self.fetch(urls[0])
          stream.meta.update(stream_metadata)
          streams.append(stream)
      else:
          with ThreadPoolExecutor() as executor:
              results = executor.map(
                  self._fetch_with_exception_suppression, urls
              )
  
          for stream_metadata, stream in results:  # type: ignore
              if stream_metadata is not None and stream is not None:
                  stream.meta.update(stream_metadata)
                  streams.append(stream)
  
      return {"streams": streams}
  
file_path: haystack/haystack/components/fetchers/link_content.py
imports: import logging
  from collections import defaultdict
  from concurrent.futures import ThreadPoolExecutor
  from typing import Callable, Dict, List, Optional, Tuple
  import requests
  from requests import Response
  from requests.exceptions import HTTPError
  from tenacity import RetryCallState, retry, retry_if_exception_type, stop_after_attempt, wait_exponential
  from haystack import component
  from haystack.dataclasses import ByteStream
  from haystack.version import __version__
label_desc: Use image node_id 2 for calling the LinkContentFetcher obj's underlying member method code with example usage: obj.run(urls) and returns: dict, dict