@@ -192,27 +192,6 @@ def __init__(
192192 proxy : Optional [Dict [str , str ]] = None ,
193193 params : Optional [Dict ] = None ,
194194 ):
195- """Concurrent document loader for FireCrawl operations.
196-
197- Executes multiple FireCrawlLoader instances concurrently using thread pooling
198- to improve bulk processing efficiency.
199- Args:
200- web_paths: List of URLs/paths to process.
201- verify_ssl: If True, verify SSL certificates.
202- trust_env: If True, use proxy settings from environment variables.
203- requests_per_second: Number of requests per second to limit to.
204- continue_on_failure (bool): If True, continue loading other URLs on failure.
205- api_key: API key for FireCrawl service. Defaults to None
206- (uses FIRE_CRAWL_API_KEY environment variable if not provided).
207- api_url: Base URL for FireCrawl API. Defaults to official API endpoint.
208- mode: Operation mode selection:
209- - 'crawl': Website crawling mode
210- - 'scrape': Direct page scraping (default)
211- - 'map': Site map generation
212- proxy: Proxy override settings for the FireCrawl API.
213- params: The parameters to pass to the Firecrawl API.
214- For more details, visit: https://docs.firecrawl.dev/sdks/python#batch-scrape
215- """
216195 proxy_server = proxy .get ('server' ) if proxy else None
217196 if trust_env and not proxy_server :
218197 env_proxies = urllib .request .getproxies ()
@@ -229,83 +208,54 @@ def __init__(
229208 self .trust_env = trust_env
230209 self .continue_on_failure = continue_on_failure
231210 self .api_key = api_key
232- self .api_url = api_url
211+ self .api_url = ( api_url or 'https://api.firecrawl.dev' ). rstrip ( '/' )
233212 self .timeout = timeout
234213 self .mode = mode
235214 self .params = params or {}
236215
237216 def lazy_load (self ) -> Iterator [Document ]:
238- """Load documents using FireCrawl batch_scrape."""
239- log .debug (
240- 'Starting FireCrawl batch scrape for %d URLs, mode: %s, params: %s' ,
241- len (self .web_paths ),
242- self .mode ,
243- self .params ,
244- )
245217 try :
246- from firecrawl import FirecrawlApp
247-
248- firecrawl = FirecrawlApp (api_key = self .api_key , api_url = self .api_url )
249- result = firecrawl .batch_scrape (
250- self .web_paths ,
251- formats = ['markdown' ],
252- skip_tls_verification = not self .verify_ssl ,
253- ignore_invalid_urls = True ,
254- remove_base64_images = True ,
255- max_age = 300000 , # 5 minutes https://docs.firecrawl.dev/features/fast-scraping#common-maxage-values
256- wait_timeout = self .timeout if self .timeout else len (self .web_paths ) * 3 ,
257- ** self .params ,
258- )
259-
260- if result .status != 'completed' :
261- raise RuntimeError (f'FireCrawl batch scrape did not complete successfully. result: { result } ' )
218+ headers = {
219+ 'Content-Type' : 'application/json' ,
220+ 'Authorization' : f'Bearer { self .api_key } ' ,
221+ }
222+
223+ for url in self .web_paths :
224+ payload = {
225+ 'url' : url ,
226+ 'formats' : ['markdown' ],
227+ ** self .params ,
228+ }
229+ if self .timeout :
230+ payload ['timeout' ] = self .timeout * 1000
231+
232+ response = requests .post (
233+ f'{ self .api_url } /v1/scrape' ,
234+ headers = headers ,
235+ json = payload ,
236+ timeout = self .timeout or 60 ,
237+ verify = self .verify_ssl ,
238+ )
239+ response .raise_for_status ()
240+ data = response .json ().get ('data' , {})
241+ metadata = data .get ('metadata' , {})
242+ source = metadata .get ('url' ) or metadata .get ('sourceURL' ) or url
262243
263- for data in result .data :
264- metadata = data .metadata or {}
265244 yield Document (
266- page_content = data .markdown or '' ,
267- metadata = {'source' : metadata . url or metadata . source_url or '' },
245+ page_content = data .get ( ' markdown' , '' ) ,
246+ metadata = {'source' : source },
268247 )
269-
270248 except Exception as e :
271249 if self .continue_on_failure :
272250 log .exception (f'Error extracting content from URLs: { e } ' )
273251 else :
274252 raise e
275253
276254 async def alazy_load (self ):
277- """Async version of lazy_load."""
278- log .debug (
279- 'Starting FireCrawl batch scrape for %d URLs, mode: %s, params: %s' ,
280- len (self .web_paths ),
281- self .mode ,
282- self .params ,
283- )
284255 try :
285- from firecrawl import FirecrawlApp
286-
287- firecrawl = FirecrawlApp (api_key = self .api_key , api_url = self .api_url )
288- result = firecrawl .batch_scrape (
289- self .web_paths ,
290- formats = ['markdown' ],
291- skip_tls_verification = not self .verify_ssl ,
292- ignore_invalid_urls = True ,
293- remove_base64_images = True ,
294- max_age = 300000 , # 5 minutes https://docs.firecrawl.dev/features/fast-scraping#common-maxage-values
295- wait_timeout = self .timeout if self .timeout else len (self .web_paths ) * 3 ,
296- ** self .params ,
297- )
298-
299- if result .status != 'completed' :
300- raise RuntimeError (f'FireCrawl batch scrape did not complete successfully. result: { result } ' )
301-
302- for data in result .data :
303- metadata = data .metadata or {}
304- yield Document (
305- page_content = data .markdown or '' ,
306- metadata = {'source' : metadata .url or metadata .source_url or '' },
307- )
308-
256+ docs = await run_in_threadpool (lambda : list (self .lazy_load ()))
257+ for doc in docs :
258+ yield doc
309259 except Exception as e :
310260 if self .continue_on_failure :
311261 log .exception (f'Error extracting content from URLs: { e } ' )
0 commit comments