Skip to content

Commit 0d48d9f

Browse files
authored
feat: add html parse api url parsing (#570)
1 parent 632eb18 commit 0d48d9f

4 files changed

Lines changed: 62 additions & 19 deletions

File tree

llm_web_kit/api/dependencies.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Settings(BaseSettings):
3131
# 模型配置
3232
model_path: Optional[str] = None
3333
max_content_length: int = 10 * 1024 * 1024 # 10MB
34+
crawl_url: str = "http://10.140.0.94:9500/crawl"
3435

3536
# 缓存配置
3637
cache_ttl: int = 3600 # 1小时

llm_web_kit/api/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ aiohttp>=3.9.0
33

44
# FastAPI 相关依赖
55
fastapi>=0.104.0
6+
httpx>=0.27.0
67
pydantic>=2.0.0
78
pydantic-settings>=2.0.0
89

llm_web_kit/api/services/html_service.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
from typing import Any, Dict, Optional
77

8-
from llm_web_kit.simple import extract_content_from_main_html
8+
import httpx
99

10-
from ..dependencies import get_inference_service, get_logger, get_settings
10+
from llm_web_kit.api.dependencies import (get_inference_service, get_logger,
11+
get_settings)
12+
from llm_web_kit.simple import extract_content_from_main_html
1113

1214
logger = get_logger(__name__)
1315
settings = get_settings()
@@ -37,8 +39,26 @@ async def parse_html(
3739
) -> Dict[str, Any]:
3840
"""解析 HTML 内容."""
3941
try:
42+
if not html_content and url:
43+
logger.info(f'HTML 内容为空,尝试从 URL 爬取: {url}')
44+
try:
45+
async with httpx.AsyncClient() as client:
46+
response = await client.post(settings.crawl_url, json={'url': url}, timeout=60)
47+
response.raise_for_status()
48+
data = response.json()
49+
html_content = data.get('html')
50+
if not html_content:
51+
raise ValueError('爬取成功,但未返回 HTML 内容')
52+
logger.info(f'URL 爬取成功,内容长度: {len(html_content)}')
53+
except httpx.RequestError as exc:
54+
logger.error(f"调用爬虫服务失败: {exc}")
55+
raise ValueError(f"无法从 URL 爬取内容: {exc}")
56+
except Exception as e:
57+
logger.error(f'爬取或解析爬取内容失败: {e}')
58+
raise ValueError(f'处理爬取内容时发生错误: {e}')
59+
4060
if not html_content:
41-
raise ValueError('必须提供 HTML 内容')
61+
raise ValueError('必须提供 HTML 内容或有效的 URL')
4262

4363
# 延迟导入,避免模块导入期异常导致服务类不可用
4464
try:
@@ -83,3 +103,21 @@ async def _parse_with_model(self, html_content: str, options: Optional[Dict[str,
83103
if self._inference_service is None:
84104
self._inference_service = get_inference_service()
85105
return await self._inference_service.inference(html_content, options or {})
106+
107+
108+
if __name__ == '__main__':
109+
import asyncio
110+
111+
# 重新导入以确保加载最新的代码,绕过缓存问题
112+
from llm_web_kit.api.dependencies import get_settings
113+
settings = get_settings()
114+
115+
async def main():
116+
async with httpx.AsyncClient() as client:
117+
response = await client.post(settings.crawl_url, json={'url': 'https://aws.amazon.com/what-is/retrieval-augmented-generation/'}, timeout=60)
118+
response.raise_for_status()
119+
data = response.json()
120+
html_content = data.get('html')
121+
print(html_content)
122+
123+
asyncio.run(main())

llm_web_kit/main_html_parser/parser/layout_batch_parser.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,25 @@ def parse(self, pre_data: PreDataJson) -> PreDataJson:
7373
content, body = self.process(html_source, template_dict_html)
7474

7575
# 相似度计算
76-
if pre_data.get(PreDataJsonKey.TYPICAL_MAIN_HTML, None):
77-
template_main_html = pre_data[PreDataJsonKey.TYPICAL_MAIN_HTML]
78-
if pre_data.get(PreDataJsonKey.SIMILARITY_LAYER, None):
79-
layer = pre_data[PreDataJsonKey.SIMILARITY_LAYER]
80-
else:
81-
layer = self.__get_max_width_layer(template_data)
82-
feature1 = get_feature(template_main_html)
83-
feature2 = get_feature(body)
84-
sim = None
85-
if feature1 is not None and feature2 is not None:
86-
sim = similarity(feature1, feature2, layer_n=layer)
87-
pre_data[PreDataJsonKey.MAIN_HTML_SIM] = sim
88-
if sim is None or sim < SIMILARITY_THRESHOLD:
89-
pre_data[PreDataJsonKey.MAIN_HTML_SUCCESS] = False
90-
else:
91-
pre_data[PreDataJsonKey.MAIN_HTML_SUCCESS] = True
76+
try:
77+
if pre_data.get(PreDataJsonKey.TYPICAL_MAIN_HTML, None):
78+
template_main_html = pre_data[PreDataJsonKey.TYPICAL_MAIN_HTML]
79+
if pre_data.get(PreDataJsonKey.SIMILARITY_LAYER, None):
80+
layer = pre_data[PreDataJsonKey.SIMILARITY_LAYER]
81+
else:
82+
layer = self.__get_max_width_layer(template_data)
83+
feature1 = get_feature(template_main_html)
84+
feature2 = get_feature(body)
85+
sim = None
86+
if feature1 is not None and feature2 is not None:
87+
sim = similarity(feature1, feature2, layer_n=layer)
88+
pre_data[PreDataJsonKey.MAIN_HTML_SIM] = sim
89+
if sim is None or sim < SIMILARITY_THRESHOLD:
90+
pre_data[PreDataJsonKey.MAIN_HTML_SUCCESS] = False
91+
else:
92+
pre_data[PreDataJsonKey.MAIN_HTML_SUCCESS] = True
93+
except Exception:
94+
pre_data[PreDataJsonKey.MAIN_HTML_SUCCESS] = None
9295

9396
# 结果返回
9497
pre_data[PreDataJsonKey.MAIN_HTML] = content

0 commit comments

Comments
 (0)