Update app2.py
Browse files
app2.py
CHANGED
@@ -434,44 +434,6 @@ def safe_find(element, selector, class_=None, attr=None):
|
|
434 |
return found.get(attr) if attr else found.text.strip()
|
435 |
return "Not available"
|
436 |
|
437 |
-
def search_lawyers(case_type: str, location: str) -> List[Dict[str, str]]:
|
438 |
-
"""
|
439 |
-
Searches for lawyers or law firms based on case type and location using web scraping from justia.com.
|
440 |
-
Returns a list of dictionaries containing lawyer/firm name, website, and description.
|
441 |
-
"""
|
442 |
-
base_url = "https://www.justia.com/lawyers/"
|
443 |
-
search_url = f"{base_url}{case_type.lower().replace(' ', '-')}-lawyer/{location.lower().replace(' ', '-')}"
|
444 |
-
|
445 |
-
headers = {
|
446 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
447 |
-
}
|
448 |
-
|
449 |
-
try:
|
450 |
-
response = requests.get(search_url, headers=headers, timeout=10)
|
451 |
-
response.raise_for_status()
|
452 |
-
soup = BeautifulSoup(response.content, 'html.parser')
|
453 |
-
|
454 |
-
lawyers = []
|
455 |
-
for lawyer in soup.find_all('div', class_='lawyer-card'):
|
456 |
-
name = safe_find(lawyer, 'h4', class_='lawyer-name')
|
457 |
-
website = safe_find(lawyer, 'a', class_='lawyer-website', attr='href')
|
458 |
-
description = safe_find(lawyer, 'p', class_='lawyer-description')
|
459 |
-
|
460 |
-
if name != "Not available" and website != "Not available":
|
461 |
-
lawyers.append({
|
462 |
-
"name": name,
|
463 |
-
"website": website,
|
464 |
-
"description": description
|
465 |
-
})
|
466 |
-
|
467 |
-
if len(lawyers) == 5:
|
468 |
-
break
|
469 |
-
|
470 |
-
return lawyers
|
471 |
-
except requests.RequestException as e:
|
472 |
-
print(f"Error fetching lawyer data: {e}")
|
473 |
-
return []
|
474 |
-
|
475 |
def search_web_duckduckgo(query: str, num_results: int = 3) -> List[Dict[str, str]]:
|
476 |
"""
|
477 |
Performs a web search using the DuckDuckGo search engine.
|
@@ -510,45 +472,6 @@ def search_web_duckduckgo(query: str, num_results: int = 3) -> List[Dict[str, st
|
|
510 |
print(f"Error fetching web search results: {e}")
|
511 |
return []
|
512 |
|
513 |
-
def search_similar_cases(case_type: str, location: str) -> List[Dict[str, str]]:
|
514 |
-
"""
|
515 |
-
Searches for similar legal cases based on case type and location using web scraping from caselaw.findlaw.com.
|
516 |
-
Returns a list of dictionaries containing case title, link, and brief description.
|
517 |
-
"""
|
518 |
-
base_url = "https://caselaw.findlaw.com/summary/"
|
519 |
-
search_query = f"{case_type.replace(' ', '-')}-{location.replace(' ', '-')}"
|
520 |
-
search_url = f"{base_url}{search_query}.html"
|
521 |
-
|
522 |
-
headers = {
|
523 |
-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
524 |
-
}
|
525 |
-
|
526 |
-
try:
|
527 |
-
response = requests.get(search_url, headers=headers, timeout=10)
|
528 |
-
response.raise_for_status()
|
529 |
-
soup = BeautifulSoup(response.content, 'html.parser')
|
530 |
-
|
531 |
-
cases = []
|
532 |
-
for case in soup.find_all('div', class_='case-summary'):
|
533 |
-
title = safe_find(case, 'h3', class_='case-name')
|
534 |
-
link = safe_find(case, 'a', class_='case-link', attr='href')
|
535 |
-
description = safe_find(case, 'p', class_='case-description')
|
536 |
-
|
537 |
-
if title != "Not available" and link != "Not available":
|
538 |
-
cases.append({
|
539 |
-
"title": title,
|
540 |
-
"link": f"https://caselaw.findlaw.com{link}",
|
541 |
-
"description": description
|
542 |
-
})
|
543 |
-
|
544 |
-
if len(cases) == 5:
|
545 |
-
break
|
546 |
-
|
547 |
-
return cases
|
548 |
-
except requests.RequestException as e:
|
549 |
-
print(f"Error fetching case data: {e}")
|
550 |
-
return []
|
551 |
-
|
552 |
def estimate_legal_costs(case_type: str, complexity: str, state: str) -> Dict[str, Any]:
|
553 |
"""
|
554 |
Estimates legal costs based on case type, complexity, and location.
|
@@ -589,9 +512,6 @@ def estimate_legal_costs(case_type: str, complexity: str, state: str) -> Dict[st
|
|
589 |
min_total = min_rate * min_hours
|
590 |
max_total = max_rate * max_hours
|
591 |
|
592 |
-
lawyers = search_lawyers(case_type, state)
|
593 |
-
similar_cases = search_similar_cases(case_type, state)
|
594 |
-
|
595 |
cost_breakdown = {
|
596 |
"Hourly rate range": f"${min_rate:.2f} - ${max_rate:.2f}",
|
597 |
"Estimated hours": f"{min_hours} - {max_hours}",
|
@@ -629,9 +549,7 @@ def estimate_legal_costs(case_type: str, complexity: str, state: str) -> Dict[st
|
|
629 |
"cost_breakdown": cost_breakdown,
|
630 |
"high_cost_areas": high_cost_areas,
|
631 |
"cost_saving_tips": cost_saving_tips,
|
632 |
-
"lawyer_recommendations": lawyers,
|
633 |
"finding_best_lawyer_tips": lawyer_tips,
|
634 |
-
"similar_cases": similar_cases,
|
635 |
"web_search_results": web_search_results
|
636 |
}
|
637 |
|
@@ -685,24 +603,6 @@ def legal_cost_estimator_ui():
|
|
685 |
for key, value in cost_estimate["cost_breakdown"].items():
|
686 |
st.write(f"**{key}:** {value}")
|
687 |
|
688 |
-
st.header("Recommended Lawyers/Law Firms")
|
689 |
-
if cost_estimate["lawyer_recommendations"]:
|
690 |
-
for lawyer in cost_estimate["lawyer_recommendations"]:
|
691 |
-
st.subheader(f"[{lawyer['name']}]({lawyer['website']})")
|
692 |
-
st.write(lawyer['description'])
|
693 |
-
st.write("---")
|
694 |
-
else:
|
695 |
-
st.write("No lawyers found for the selected criteria.")
|
696 |
-
|
697 |
-
st.header("Similar Cases")
|
698 |
-
if cost_estimate["similar_cases"]:
|
699 |
-
for case in cost_estimate["similar_cases"]:
|
700 |
-
st.subheader(f"[{case['title']}]({case['link']})")
|
701 |
-
st.write(case["description"])
|
702 |
-
st.write("---")
|
703 |
-
else:
|
704 |
-
st.write("No similar cases found for the selected criteria.")
|
705 |
-
|
706 |
st.header("Potential High-Cost Areas")
|
707 |
for area in cost_estimate["high_cost_areas"]:
|
708 |
st.write(f"- {area}")
|
|
|
434 |
return found.get(attr) if attr else found.text.strip()
|
435 |
return "Not available"
|
436 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
437 |
def search_web_duckduckgo(query: str, num_results: int = 3) -> List[Dict[str, str]]:
|
438 |
"""
|
439 |
Performs a web search using the DuckDuckGo search engine.
|
|
|
472 |
print(f"Error fetching web search results: {e}")
|
473 |
return []
|
474 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
475 |
def estimate_legal_costs(case_type: str, complexity: str, state: str) -> Dict[str, Any]:
|
476 |
"""
|
477 |
Estimates legal costs based on case type, complexity, and location.
|
|
|
512 |
min_total = min_rate * min_hours
|
513 |
max_total = max_rate * max_hours
|
514 |
|
|
|
|
|
|
|
515 |
cost_breakdown = {
|
516 |
"Hourly rate range": f"${min_rate:.2f} - ${max_rate:.2f}",
|
517 |
"Estimated hours": f"{min_hours} - {max_hours}",
|
|
|
549 |
"cost_breakdown": cost_breakdown,
|
550 |
"high_cost_areas": high_cost_areas,
|
551 |
"cost_saving_tips": cost_saving_tips,
|
|
|
552 |
"finding_best_lawyer_tips": lawyer_tips,
|
|
|
553 |
"web_search_results": web_search_results
|
554 |
}
|
555 |
|
|
|
603 |
for key, value in cost_estimate["cost_breakdown"].items():
|
604 |
st.write(f"**{key}:** {value}")
|
605 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
606 |
st.header("Potential High-Cost Areas")
|
607 |
for area in cost_estimate["high_cost_areas"]:
|
608 |
st.write(f"- {area}")
|