fix: _parse
This commit is contained in:
+26
-17
@@ -66,30 +66,39 @@ class IPInfo:
|
||||
def _parse(self, html: str) -> Optional[IPInfoModel]:
|
||||
"""Парсит HTML и возвращает модель"""
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
script = soup.find('script', type='application/ld+json')
|
||||
|
||||
if not script or not script.string:
|
||||
scripts = soup.find_all('script', type='application/ld+json')
|
||||
|
||||
if not scripts:
|
||||
return None
|
||||
|
||||
try:
|
||||
data: Dict = json.loads(script.string.strip())
|
||||
except json.JSONDecodeError:
|
||||
|
||||
# Ищем первый скрипт с типом DataFeed
|
||||
data = None
|
||||
for script in scripts:
|
||||
if not script.string:
|
||||
continue
|
||||
|
||||
try:
|
||||
parsed = json.loads(script.string.strip())
|
||||
if parsed.get('@type') == 'DataFeed':
|
||||
data = parsed
|
||||
break
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
if data.get('@type') != 'DataFeed':
|
||||
return None
|
||||
|
||||
|
||||
# Базовые поля
|
||||
result = IPInfoModel(
|
||||
ip=data.get('name', ''),
|
||||
url=data.get('url')
|
||||
)
|
||||
|
||||
|
||||
# Парсим локацию
|
||||
location = data.get('contentLocation', {})
|
||||
address = location.get('address', {})
|
||||
geo = location.get('geo', {})
|
||||
|
||||
|
||||
result.location = LocationModel(
|
||||
city=address.get('addressLocality'),
|
||||
region=address.get('addressRegion'),
|
||||
@@ -99,20 +108,20 @@ class IPInfo:
|
||||
longitude=geo.get('longitude'),
|
||||
timezone=self._find_value(data, 'Timezone')
|
||||
)
|
||||
|
||||
|
||||
# Парсим ASN
|
||||
result.asn = ASNModel(
|
||||
asn=self._find_value(data, 'ASN'),
|
||||
name=self._find_value(data, 'AS Name'),
|
||||
route=self._find_value(data, 'AS Route')
|
||||
)
|
||||
|
||||
|
||||
# Парсим компанию
|
||||
result.company = CompanyModel(
|
||||
name=self._find_value(data, 'Company Name'),
|
||||
abuse_contact=self._find_value(data, 'Abuse Contact')
|
||||
)
|
||||
|
||||
|
||||
# Парсим безопасность
|
||||
result.security = SecurityModel(
|
||||
vpn=self._find_bool(data, 'VPN'),
|
||||
@@ -120,7 +129,7 @@ class IPInfo:
|
||||
tor=self._find_bool(data, 'Tor'),
|
||||
hosting=self._find_bool(data, 'Hosting')
|
||||
)
|
||||
|
||||
|
||||
return result
|
||||
|
||||
def _find_value(self, data: Dict, name: str) -> Optional[str]:
|
||||
|
||||
Reference in New Issue
Block a user