dmfelder commited on
Commit
9033dfd
·
verified ·
1 Parent(s): b9b8c57

Create web_page_information_extractor.py

Browse files
tools/web_page_information_extractor.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from io import StringIO
3
+
4
+ import html2text
5
+ import pandas as pd
6
+ import requests
7
+ from bs4 import BeautifulSoup
8
+ from langchain_core.messages import SystemMessage, HumanMessage
9
+ from langchain_core.tools import tool
10
+ from langchain_openai import ChatOpenAI
11
+ from loguru import logger
12
+ from pydantic import SecretStr
13
+
14
+
15
+ @tool("web_page_information_extractor_tool", parse_docstring=True)
16
+ def web_page_information_extractor(url: str, request: str) -> str:
17
+ """
18
+ Extracts specific information from a web page based on the user's request.
19
+ This function uses a language model to extract information from the content
20
+ of a web page specified by the URL. The user's request specifies the type of
21
+ information to be extracted. The function returns the extracted information as
22
+ a JSON string.
23
+ Args:
24
+ url (str): The URL of the web page to extract information from.
25
+ request (str): The user's request describing the information to extract.
26
+ Returns:
27
+ str: The extracted information in JSON format.
28
+ """
29
+ logger.info(f"use web_page_information_extractor with param: url:{url}, request:{request}")
30
+
31
+ text = _get_text_from_url(url)
32
+ logger.debug(f"web_page_information_extractor text: {text}")
33
+
34
+ chat = ChatOpenAI(
35
+ model="gpt-4o-mini",
36
+ temperature=0,
37
+ api_key=SecretStr(os.environ['OPENAI_API_KEY'])
38
+ )
39
+
40
+ system_message = "You are an expert information extraction system. Respond ONLY with valid JSON based on the user's request."
41
+ extraction_user_prompt = f"""From the text below:\n\"\"\"\n{text}\n\"\"\"\n\nExtract the following: "{request}"."""
42
+
43
+ extracted_information = chat.invoke([
44
+ SystemMessage(system_message),
45
+ HumanMessage(extraction_user_prompt)
46
+ ])
47
+ return extracted_information.content
48
+
49
+ def _get_text_from_url(url: str) -> str:
50
+ response = requests.get(url, timeout=15, headers={"User-Agent": "Mozilla/5.0"})
51
+ response.raise_for_status() # Raises HTTPError for bad responses
52
+ html = response.text
53
+
54
+ soup = BeautifulSoup(html, "html.parser")
55
+
56
+ # Get tables
57
+ tables = soup.find_all('table', class_='wikitable')
58
+ tables_text = ""
59
+
60
+ for i, table in enumerate(tables, 1):
61
+ # Find the nearest preceding h2 or h3 header
62
+ header = table.find_previous(['h2', 'h3'])
63
+ section_title = header.get_text().strip() if header else "Untitled Section"
64
+ try:
65
+ # Convert table to pandas DataFrame using StringIO
66
+ table_html = str(table).replace('\n', '') # Remove newlines for better parsing
67
+ df = pd.read_html(StringIO(table_html))[0]
68
+
69
+ # Format the table with section title, context, and clean layout
70
+ tables_text += f"\nSection: {section_title}\n"
71
+ tables_text += "=" * 40 + "\n"
72
+ tables_text += df.to_string(index=False) + "\n\n"
73
+ except Exception as e:
74
+ tables_text += f"\nError processing table in section {section_title}: {str(e)}\n"
75
+ continue
76
+
77
+ # Step 3: Convert HTML to Markdown
78
+ markdown_converter = html2text.HTML2Text()
79
+ markdown_converter.ignore_links = False
80
+ markdown_converter.bypass_tables = False
81
+ markdown_converter.ignore_images = True # optional
82
+ markdown_converter.body_width = 0 # don't wrap lines
83
+
84
+ text = markdown_converter.handle(html)
85
+ if tables_text:
86
+ text = f'Tables:\n{tables_text}\n\nContent\n{text}'
87
+
88
+ return text
89
+
90
+ if __name__ == "__main__":
91
+ # result = web_page_information_extractor.invoke(
92
+ # {"url": "https://en.wikipedia.org/wiki/Python_(programming_language)",
93
+ # "request": "What are changes introduced in Python 3.11"})
94
+ # print(result)
95
+
96
+ result = web_page_information_extractor.invoke(
97
+ {"url": "https://en.wikipedia.org/wiki/1928_Summer_Olympics",
98
+ "request": "List of countries and number of athletes at the 1928 Summer Olympics"})
99
+ print(result)
100
+
101
+ # result = web_page_information_extractor.invoke(
102
+ # {"url": "https://chem.libretexts.org/Courses/Chabot_College/Introduction_to_General_Organic_and_Biochemistry/01%3A_Chemistry_in_our_Lives/1.E%3A_Exercises",
103
+ # "request": "What is the surname of the equine veterinarian mentioned"})
104
+ # print(result)
105
+
106
+ print(_get_text_from_url("https://en.wikipedia.org/wiki/Malko_Competition"))