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