Skip to content

Commit 8836f15

Browse files
committed
chg: [interactive crawler] better error tracking and show error to user + forum account, only create cookiejar
1 parent 8134ea1 commit 8836f15

4 files changed

Lines changed: 102 additions & 15 deletions

File tree

bin/crawlers/Crawler.py

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -207,25 +207,34 @@ def get_message(self):
207207
capture_start = capture.get_start_time(r_str=False)
208208
if capture_start == 0:
209209
task = capture.get_task()
210+
error_message = f'Lacus returned an unknown capture state for task {task.uuid}'
211+
crawlers.set_interactive_session_error_by_capture(capture.uuid, error_message)
210212
task.delete()
211213
capture.delete()
212214
self.logger.warning(f'capture UNKNOWN ERROR STATE, {task.uuid} Removed from queue')
213215
return None
214216
if int(time.time()) - capture_start > 600: # TODO ADD in new crawler config
215217
task = capture.get_task()
216-
task.reset()
217-
capture.delete()
218-
self.logger.warning(f'capture UNKNOWN Timeout, {task.uuid} Send back in queue')
218+
error_message = f'Lacus capture UNKNOWN timeout for task {task.uuid}'
219+
if crawlers.set_interactive_session_error_by_capture(capture.uuid, error_message):
220+
self.logger.warning(f'capture UNKNOWN Timeout, {task.uuid} Interactive session failed')
221+
else:
222+
task.reset()
223+
capture.delete()
224+
self.logger.warning(f'capture UNKNOWN Timeout, {task.uuid} Send back in queue')
219225
else:
220226
capture.update(status)
221227
elif status == crawlers.CaptureStatus.QUEUED:
222228
capture_start = capture.get_start_time(r_str=False)
223229
if int(time.time()) - capture_start > 36000: # TODO ADD in new crawler config
224230
task = capture.get_task()
225-
task.reset()
226-
capture.delete()
227-
self.logger.warning(
228-
f'capture QUEUED Timeout, {task.uuid}, {task.get_url()} Send back in queue, start_time={capture_start}')
231+
error_message = f'Lacus capture QUEUED timeout for task {task.uuid}'
232+
if crawlers.set_interactive_session_error_by_capture(capture.uuid, error_message):
233+
self.logger.warning(f'capture QUEUED Timeout, {task.uuid}, {task.get_url()} Interactive session failed, start_time={capture_start}')
234+
else:
235+
task.reset()
236+
capture.delete()
237+
self.logger.warning(f'capture QUEUED Timeout, {task.uuid}, {task.get_url()} Send back in queue, start_time={capture_start}')
229238
else:
230239
capture.update(status)
231240
print(capture.uuid, crawlers.CaptureStatus(status).name, int(time.time()))
@@ -235,9 +244,13 @@ def get_message(self):
235244
# Invalid State
236245
else:
237246
task = capture.get_task()
238-
task.reset()
239-
capture.delete()
240-
self.logger.warning(f'ERROR INVALID CAPTURE STATUS {status}, {task.uuid} Send back in queue')
247+
error_message = f'Lacus returned invalid capture status {status} for task {task.uuid}'
248+
if crawlers.set_interactive_session_error_by_capture(capture.uuid, error_message):
249+
self.logger.warning(f'ERROR INVALID CAPTURE STATUS {status}, {task.uuid} Interactive session failed')
250+
else:
251+
task.reset()
252+
capture.delete()
253+
self.logger.warning(f'ERROR INVALID CAPTURE STATUS {status}, {task.uuid} Send back in queue')
241254

242255
except ConnectionError:
243256
self.logger.warning(f'Lacus ConnectionError, capture {capture.uuid}')
@@ -334,6 +347,20 @@ def compute(self, capture): # TODO ADD FUNCTION TO MANUALLY IMPORT ???
334347
entries = self.lacus.get_capture(capture.uuid)
335348

336349
print(entries.get('status'))
350+
if task.is_cookiejar_only():
351+
if entries.get('error'):
352+
error_message = str(entries['error'])
353+
self.logger.warning(error_message)
354+
crawlers.set_interactive_session_error_by_capture(capture.uuid, error_message)
355+
else:
356+
cookiejar_saved = crawlers.finalize_interactive_cookiejar_session(capture.uuid, entries.get('storage', {}))
357+
if cookiejar_saved is False:
358+
crawlers.release_interactive_session_by_capture(capture.uuid, status='error')
359+
else:
360+
crawlers.release_interactive_session_by_capture(capture.uuid, status='completed')
361+
task.remove()
362+
self.root_item = None
363+
return None
337364
self.har = task.get_har()
338365
self.screenshot = task.get_screenshot()
339366
# DEBUG
@@ -399,11 +426,15 @@ def compute(self, capture): # TODO ADD FUNCTION TO MANUALLY IMPORT ???
399426

400427
def save_capture_response(self, capture, task, parent_id, entries):
401428
filter_page = False
429+
crawled_domain = None
430+
crawled_url = None
402431
print(entries.keys())
403432
if 'error' in entries:
404433
# TODO IMPROVE ERROR MESSAGE
405434
error_message = str(entries['error'])
406435
self.logger.warning(str(entries['error']))
436+
if crawlers.set_interactive_session_error_by_capture(capture.uuid, error_message):
437+
return False
407438
if error_message.startswith('Something went poorly'):
408439
# Timeout, require restart of lacus
409440
if 'Too many open files' in error_message:
@@ -559,11 +590,16 @@ def save_capture_response(self, capture, task, parent_id, entries):
559590
fav = Favicons.create(favicon)
560591
fav.add(item.get_date(), item)
561592

593+
crawled_domain = self.domain.id
594+
crawled_url = last_url
595+
562596
# Next Children
563597
entries_children = entries.get('children')
564598
if entries_children:
565599
for children in entries_children:
566600
self.save_capture_response(capture, task, parent_id, children)
601+
if crawled_domain:
602+
crawlers.set_interactive_session_crawled_domain_by_capture(capture.uuid, crawled_domain, url=crawled_url)
567603
return True
568604

569605

bin/lib/crawlers.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,6 +2393,21 @@ def get_interactive_session_by_capture(capture_uuid):
23932393
return session
23942394
return None
23952395

2396+
def set_interactive_session_error_by_capture(capture_uuid, error_message, status='error'):
2397+
session = get_interactive_session_by_capture(capture_uuid)
2398+
if session and session.exists():
2399+
session.set('error', str(error_message))
2400+
session.release(status=status)
2401+
return True
2402+
return False
2403+
2404+
def set_interactive_session_crawled_domain_by_capture(capture_uuid, domain, url=None):
2405+
session = get_interactive_session_by_capture(capture_uuid)
2406+
if session and session.exists():
2407+
session.set('crawled_domain', domain)
2408+
if url:
2409+
session.set('crawled_url', url)
2410+
23962411
def release_interactive_session_by_capture(capture_uuid, status='completed'):
23972412
session = get_interactive_session_by_capture(capture_uuid)
23982413
if session and session.exists():
@@ -2454,12 +2469,12 @@ def _remote_headed_response_to_meta(response):
24542469
def finalize_interactive_cookiejar_session(capture_uuid, storage):
24552470
session = get_interactive_session_by_capture(capture_uuid)
24562471
if not session or session.get('save_cookiejar') != '1':
2457-
return
2472+
return None
24582473
try:
24592474
if not storage or not isinstance(storage, dict):
24602475
print('storage error')
24612476
session.set('error', 'No cookies or local storage returned by the interactive browser')
2462-
return
2477+
return False
24632478
cookiejar_uuid = create_cookiejar(session.get('user_org'), session.get_user(), session.get('cookiejar_description'), 0, None)
24642479
print(f'New cookiejar {cookiejar_uuid}')
24652480
cookiejar = Cookiejar(cookiejar_uuid)
@@ -2476,8 +2491,10 @@ def finalize_interactive_cookiejar_session(capture_uuid, storage):
24762491
account.set_cookiejar_uuid(cookiejar_uuid)
24772492
account.set_status('waiting')
24782493
forum.refresh_account_availability(account_id)
2494+
return True
24792495
except Exception as e:
24802496
session.set('error', str(e))
2497+
return False
24812498

24822499
def refresh_interactive_session_status(session):
24832500
capture_uuid = session.get_capture_uuid()
@@ -2578,14 +2595,29 @@ def api_start_interactive_capture(data, user_org, user_id):
25782595
if error:
25792596
return error, code
25802597
try:
2581-
task_uuid = create_task(task['url'], depth=0, har=task['har'], screenshot=task['screenshot'], proxy=task['proxy'], tags=task['tags'], parent='interactive', priority=90, external=True)
2598+
cookiejar_only = bool(data.get('cookiejar_only'))
2599+
if cookiejar_only:
2600+
har = False
2601+
screenshot = False
2602+
tags = []
2603+
with_favicon = False
2604+
else:
2605+
har = task['har']
2606+
screenshot = task['screenshot']
2607+
tags = task['tags']
2608+
with_favicon = True
2609+
2610+
task_uuid = create_task(task['url'], depth=0, har=har, screenshot=screenshot, proxy=task['proxy'], tags=tags, parent='interactive', priority=90, external=True)
25822611
if not task_uuid:
25832612
session.release(status='error')
25842613
return {'error': 'Aborted by Crawler'}, 400
25852614
session.set('task_uuid', task_uuid)
2615+
if cookiejar_only:
2616+
CrawlerTask(task_uuid).set_cookiejar_only()
2617+
session.set('cookiejar_only', '1')
25862618
capture_uuid = session.uuid
25872619
lacus = get_lacus()
2588-
returned_uuid = lacus.enqueue(url=task['url'], depth=0, proxy=task['proxy'], with_favicon=True, force=True, uuid=capture_uuid, remote_headfull=True, java_script_enabled=task['javascript'], general_timeout_in_sec=int(data.get('general_timeout_in_sec') or 90))
2620+
returned_uuid = lacus.enqueue(url=task['url'], depth=0, proxy=task['proxy'], with_favicon=with_favicon, force=True, uuid=capture_uuid, remote_headfull=True, java_script_enabled=task['javascript'], general_timeout_in_sec=int(data.get('general_timeout_in_sec') or 90))
25892621
capture_uuid = returned_uuid or capture_uuid
25902622
session.set('capture_uuid', capture_uuid)
25912623
r_cache.hset('crawler:interactive:captures', capture_uuid, session.uuid)
@@ -2849,6 +2881,12 @@ def get_har(self):
28492881
def get_screenshot(self):
28502882
return r_crawler.hget(f'crawler:task:{self.uuid}', 'screenshot') == '1'
28512883

2884+
def is_cookiejar_only(self):
2885+
return r_crawler.hget(f'crawler:task:{self.uuid}', 'cookiejar_only') == '1'
2886+
2887+
def set_cookiejar_only(self):
2888+
return self._set_field('cookiejar_only', 1)
2889+
28522890
def get_queue(self):
28532891
return r_crawler.hget(f'crawler:task:{self.uuid}', 'queue')
28542892

var/www/blueprints/forums_explorer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def forum_explorer_crawler_account_interactive_cookiejar():
202202
'javascript': config.get('javascript'),
203203
'general_timeout_in_sec': 300,
204204
'save_cookiejar': True,
205+
'cookiejar_only': True,
205206
}
206207
user_org = current_user.get_org()
207208
user_id = current_user.get_user_id()

var/www/templates/crawler/crawler_splash/interactive_capture.html

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@
2525
{% endif %}
2626
<p id="remote_status_row" {% if not session.remote_status or session.status in ['finishing', 'completed', 'expired', 'error', 'closed'] %}style="display:none;"{% endif %}><b>Remote browser status:</b> <span id="remote_status">{{ session.remote_status }}</span></p>
2727
<p id="capture_status_row" {% if not session.capture_status %}style="display:none;"{% endif %}><b>Capture status:</b> <span id="capture_status">{{ session.capture_status }}</span></p>
28+
<p id="crawled_domain_row" {% if not session.crawled_domain %}style="display:none;"{% endif %}>
29+
<b>Crawled domain:</b>
30+
<span id="crawled_url" class="text-muted" {% if not session.crawled_url %}style="display:none;"{% endif %}>({{ session.crawled_url }})</span>
31+
<a id="crawled_domain_link" href="{{ url_for('crawler_splash.showDomain') }}?domain={{ session.crawled_domain|urlencode }}">{{ session.crawled_domain }}</a>
32+
</p>
2833
<a id="remote_url_btn" class="btn btn-primary" target="_blank" rel="noopener" href="{{ session.remote_url }}" {% if not session.remote_url or session.status in ['finishing', 'completed', 'expired', 'error', 'closed'] %}style="display:none;"{% endif %}><i class="fas fa-external-link-alt"></i> Open interactive browser</a>
2934
<div id="remote_starting" class="alert alert-info" {% if session.remote_url or session.status in ['finishing', 'completed', 'expired', 'error', 'closed'] %}style="display:none;"{% endif %}>
3035
The interactive browser is starting. This page updates automatically; the browser link will appear as soon as it is ready.
3136
</div>
3237
<div id="capture_processing" class="alert alert-success" {% if session.status not in ['finishing', 'completed'] %}style="display:none;"{% endif %}>
33-
The interactive session is completed. AIL is saving and processing the browser state; results will appear in AIL when processing is finished.
38+
The interactive session is completed. AIL is saving and processing the browser state; results URL will appear in AIL when processing is finished.
3439
</div>
3540
{% if session.status in ['starting', 'ready'] %}
3641
<form class="mt-3" method="post" action="{{ url_for('crawler_splash.interactive_capture_finish', uuid=session.uuid) }}">
@@ -79,6 +84,13 @@
7984
$('#cookiejar_link').attr('href', '{{ url_for('crawler_splash.crawler_cookiejar_show') }}?uuid=' + data.cookiejar_uuid).text(data.cookiejar_uuid);
8085
$('#cookiejar_row').show();
8186
}
87+
if(data.crawled_domain){
88+
$('#crawled_domain_link').attr('href', '{{ url_for('crawler_splash.showDomain') }}?domain=' + encodeURIComponent(data.crawled_domain)).text(data.crawled_domain);
89+
if(data.crawled_url){
90+
$('#crawled_url').text('(' + data.crawled_url + ')').show();
91+
}
92+
$('#crawled_domain_row').show();
93+
}
8294
if(data.error || data.last_status_error){
8395
$('#interactive_error').text(data.error || data.last_status_error).show();
8496
}

0 commit comments

Comments
 (0)