first commit

This commit is contained in:
leca 2025-02-14 14:21:16 +03:00
parent ff60106b5d
commit f16dee972d
26 changed files with 691 additions and 0 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Poetry (worker-parser)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (worker-parser)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/worker-parser.iml" filepath="$PROJECT_DIR$/.idea/worker-parser.iml" />
</modules>
</component>
</project>

8
.idea/worker-parser.iml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Poetry (worker-parser)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_nsis.ru FALSE / TRUE 0 __admin_identity 4727b737cc09d1bf39712670799d25ca
#HttpOnly_nsis.ru FALSE / FALSE 1739551116 session-cookie 1823d1f145254dd74164466d18991a2473af815cc6c8fe97e15b8d5c2dbddb9153e270c545025afca83ab0de600f80f6

View File

@ -0,0 +1,107 @@
<!DOCTYPE html>
<div id=\"resp\" data-js-modal=\"\" class=\"modal modal--isWidth105 modal--isRowGapSonMobile\">
<div class=\"modal__inner\">
<header class=\"modal__header\">
<div class=\"modal__title\">Данные о полисах ОСАГО</div>
</header>
<div data-js-modal-content=\"\" class=\"modal__content\">
<div class=\"policyDataModal policyDataModal--isMorePolicy\">
<div class=\"policyDataModal__dateSlot\">
<div class=\"tag tag--isColorEbonyClay tag--isWdMaxContent \">
<span style=\"text-transform: inherit\";>на 13.02.2025</span>
</div>
</div>
<div class=\"policyDataModal__content\">
<div class=\"spoiler spoiler--isWholeHeaderClickable spoiler--isColorSmalt spoiler--isSizeMedium\"
data-js-spoiler=\"{&quot;isWholeHeaderClickable&quot;:true,&quot;isOpened&quot;:true}\">
<div class=\"spoiler__header spoiler__header--isCustomHeader\" data-js-spoilerheader=\"\">
<div>
<div
class=\"dataList dataList--isValueTextAlignRight dataList--isDirectionHorizontal dataList--isItemDirectionHorizontal dataList--isMarginBottomXs dataList--isDirectionVertical dataList--isItemDirectionVertical\">
<dl class=\"dataList__list\">
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Серия полиса:</span>
</dt>
<dd class=\"dataList__value\">ХХХ</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Номер полиса:</span>
</dt>
<dd class=\"dataList__value\">0471415698</dd>
</div>
</dl>
</div>
</div>
<div class=\"spoiler__toggleBtn\">
<button draggable=\"false\" type=\"button\" class=\"btn btn--isOnlyIcon btn--isSizeMedium\"
data-js-spoilertogglebtn=\"\">
<span class=\"btn__icon\">
<span role=\"presentation\" class=\"icon icon--isSizeMedium\">
<svg class=\"icon__src\">
<use href=\"#icon-dropdown\" />
</svg>
</span>
</span>
</button>
</div>
</div>
<div class=\"spoiler__content\" data-js-spoilercontent=\"\">
<div class=\"spoiler__contentInner\">
<div class=\"dataList dataList--isValueTextAlignRight dataList--isItemDirectionHorizontal dataList--isSeparatorBorder dataList--isItemPaddingYM dataList--isItemLabelBasis60 dataList--isDirectionVertical dataList--isItemDirectionVertical\">
<dl class=\"dataList__list\">
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Статус договора ОСАГО:</span>
</dt>
<dd class=\"dataList__value\">Действует</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Период использования:</span>
</dt>
<dd class=\"dataList__value dataList__value--isChildren\">
<span>Период использования транспортного средства равен сроку страхования. Дата, на которую запрошены сведения, входит в период использования транспортного средства</span>
</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Марка и модель ТС:</span>
</dt>
<dd class=\"dataList__value\">Mercedes-Benz GLS-class</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Идентификационный номер транспортного средства:</span>
</dt>
<dd class=\"dataList__value\">W1N1679591A2*****</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Государственный регистрационный знак:</span>
</dt>
<dd class=\"dataList__value\">М9***М777</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Страховая компания:</span>
</dt>
<dd class=\"dataList__value\">Страховое публичное акционерное общество \"Ингосстрах\"</dd>
</div>
<div class=\"dataList__item\">
<dt class=\"dataList__label\">
<span class=\"dataList__labelText\">Расширение на территорию Республики Беларусь:</span>
</dt>
<dd class=\"dataList__value\">Нет</dd>
</div>
</dl>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<!DOCTYPE html>\n<div id=\"modal-policy-not-found\" data-js-modal=\"\" class=\"modal modal--isContentCenter\">\n <div class=\"modal__inner\">\n <div data-js-modal-content=\"\" class=\"modal__content\">\n <img class=\"isMb3\" loading=\"lazy\" width=\"64\" height=\"64\" src=\"/assets/assets/images/cancel.svg\" alt=\"Отмена\" />\n <p>Сведения о договоре ОСАГО с указанными Вами данными не найдены в АИС страхования</p>\n </div>\n </div>\n</div>

10
api-playground/first-request.sh Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
curl \
'https://nsis.ru/handle-form/1314895756519276544/' \
-X POST \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Content-Type: multipart/form-data; boundary=---------------------------330424154228665440354056616977' \
-c cookies.txt -b cookies.txt \
--data-binary $'-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="licenseplate"\r\n\r\nМ976ММ777\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="requestdate"\r\n\r\n2025-02-13' \
| jq ".data.processId"

View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
curl 'https://nsis.ru/handle-form/1314895756519276544/' \
--compressed \
-X POST \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0' \
-H 'Accept: */*' \
-H 'Accept-Language: en-US,en;q=0.5' \
-H 'Accept-Encoding: gzip, deflate, br, zstd' \
-H 'Referer: https://nsis.ru/products/osago/check/' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Content-Type: multipart/form-data; boundary=---------------------------330424154228665440354056616977' \
-H 'Origin: https://nsis.ru' \
-H 'DNT: 1' \
-H 'Connection: keep-alive' \
-H 'Cookie: __admin_identity=303e52d06800f984bacc16e01fc8b5d3; session-cookie=1823b7a9083bd9a9eaada86db4819f5b9ae81958117396cce64fc9bee2d791a890ce1ff64b2c9e6c6b4850b9ddee7b0e' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'Priority: u=0' --data-binary $'-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="licenseplate"\r\n\r\n\u041c976\u041c\u041c777\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="requestdate"\r\n\r\n2025-02-13\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="idExternal"\r\n\r\n\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="vin"\r\n\r\n\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="bodynumber"\r\n\r\n\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="chassisnumber"\r\n\r\n\r\n-----------------------------330424154228665440354056616977--\r\n' \
| jq ".isSuccess"

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
curl \
'https://nsis.ru/handle-form/1314895756519276544/' \
-X POST \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Content-Type: multipart/form-data; boundary=---------------------------330424154228665440354056616977' \
-c cookies.txt -b cookies.txt \
--data-binary $'-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="licenseplate"\r\n\r\n\u041c976\u041c\u041c777\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="requestdate"\r\n\r\n2025-02-13' \
#| jq ".isSuccess"

View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# 00000000-0000-0000-75bc-93dc420288e3
curl \
'https://nsis.ru/api/v1/status/00000000-0000-0000-bb1c-2353d446bf47/?formCode=check_osago_fact_transport' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Content-Type: multipart/form-data; boundary=---------------------------330424154228665440354056616977' \
-c cookies.txt -b cookies.txt | jq ".modals.html"

View File

@ -0,0 +1,19 @@
#!/usr/bin/env bash
curl \
'https://nsis.ru/api/v1/status/$1/?formCode=check_osago_fact_transport' \
--compressed \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:134.0) Gecko/20100101 Firefox/134.0' \
-H 'Accept: */*' \
-H 'Accept-Language: en-US,en;q=0.5' \
-H 'Accept-Encoding: gzip, deflate, br, zstd' \
-H 'Referer: https://nsis.ru/products/osago/check/' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'Content-Type: application/json' \
-H 'DNT: 1' \
-H 'Connection: keep-alive' \
-c cookies.txt -b cookies.txt \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-origin' \
-H 'Priority: u=4'

228
poetry.lock generated Normal file
View File

@ -0,0 +1,228 @@
# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
[[package]]
name = "beautifulsoup4"
version = "4.13.3"
description = "Screen-scraping library"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16"},
{file = "beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b"},
]
[package.dependencies]
soupsieve = ">1.2"
typing-extensions = ">=4.0.0"
[package.extras]
cchardet = ["cchardet"]
chardet = ["chardet"]
charset-normalizer = ["charset-normalizer"]
html5lib = ["html5lib"]
lxml = ["lxml"]
[[package]]
name = "certifi"
version = "2025.1.31"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"},
{file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"},
]
[[package]]
name = "charset-normalizer"
version = "3.4.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false
python-versions = ">=3.7"
files = [
{file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"},
{file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"},
{file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"},
{file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"},
{file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"},
{file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"},
{file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"},
{file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"},
{file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"},
{file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"},
{file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"},
{file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"},
{file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"},
{file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"},
{file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"},
{file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"},
{file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"},
{file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"},
{file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"},
{file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"},
{file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"},
{file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"},
{file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"},
{file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"},
{file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"},
{file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"},
{file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"},
{file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"},
{file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"},
{file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"},
{file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"},
{file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"},
{file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"},
]
[[package]]
name = "idna"
version = "3.10"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.6"
files = [
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
]
[package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
name = "python-dotenv"
version = "1.0.1"
description = "Read key-value pairs from a .env file and set them as environment variables"
optional = false
python-versions = ">=3.8"
files = [
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
]
[package.extras]
cli = ["click (>=5.0)"]
[[package]]
name = "requests"
version = "2.32.3"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.8"
files = [
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "soupsieve"
version = "2.6"
description = "A modern CSS selector implementation for Beautiful Soup."
optional = false
python-versions = ">=3.8"
files = [
{file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"},
{file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"},
]
[[package]]
name = "typing-extensions"
version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "urllib3"
version = "2.3.0"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.9"
files = [
{file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"},
{file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.13"
content-hash = "065d3304e2c109bd2e532e78c355b38f7efe9ec9df2d96a6ab409e91e9cfe628"

1
proxies.txt Normal file
View File

@ -0,0 +1 @@
#format: ip:port:type(SOCKS(4/5)/HTTP):

17
pyproject.toml Normal file
View File

@ -0,0 +1,17 @@
[tool.poetry]
name = "worker-parser"
version = "0.1.0"
description = ""
authors = ["leca <leca@foxarmy.org>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.13"
requests = "^2.32.3"
beautifulsoup4 = "^4.13.3"
python-dotenv = "^1.0.1"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

13
src/__main__.py Normal file
View File

@ -0,0 +1,13 @@
import asyncio
import dotenv
import os
from src.services.worker import Worker
if __name__ == "__main__":
worker = Worker()
dotenv.load_dotenv()
workers_amount = int(os.getenv("WORKERS_AMOUNT"))
for i in range(0, workers_amount):
asyncio.run(worker.process())

View File

@ -0,0 +1 @@
from src.dataclasses.task import Task

View File

@ -0,0 +1,13 @@
from enum import Enum
class LogLevels(Enum):
"""
LogLevels enumerates available log levels, from the most verbose(debug) to the silentest(error)
"""
def __gt__(self, other):
return self.value > other.value
DEBUG = 0
INFO = 1
WARNING = 2
ERROR = 3

22
src/dataclasses/task.py Normal file
View File

@ -0,0 +1,22 @@
import datetime
"""
This file contains definitions for Task class and its subclasses.
"""
class Task:
"""
An abstract class used to create hierarchy and upcasts/downcasts when working with tasks.
"""
pass
class RequestTsInfoTask(Task):
"""
Subclass of a Task class, contains data needed to request data about a vehicle from https://nsis.ru/products/osago/check/.
"""
def __init__(self, license_plate: str, prior_to_date: datetime):
self.license_plate = license_plate
self.prior_to_date = prior_to_date

2
src/services/__init__.py Normal file
View File

@ -0,0 +1,2 @@
from src.services.dummy_broker import Broker
from src.services.worker import Worker

View File

@ -0,0 +1,26 @@
from datetime import date
from src.dataclasses.task import RequestTsInfoTask, Task
class Broker:
"""
Serves as a dummy broker to simulate broker's work and supply workers with tasks queue
"""
def __init__(self):
"""
Task queue is a list that contains tasks sorted by their priority
"""
self.tasks_queue = list()
self.tasks_queue.append(RequestTsInfoTask("М976ММ777", date.today()))
def get_task(self) -> Task | None:
"""
Return uncompleted task with the highest priority.
Return None if no tasks are available.
"""
if len(self.tasks_queue) == 0: return None
task = self.tasks_queue.pop()
return task

34
src/services/logger.py Normal file
View File

@ -0,0 +1,34 @@
from io import FileIO
from sys import stdout
from time import time
from typing import IO
from src.dataclasses.loglevels import LogLevels
class Logger:
"""
Logger is a class that handles logging to the STDOUT of a file.
Upon creating one must specify the maximum log level.
Logger will not log the messages with
"""
def __init__(self, loglevel: LogLevels, place_to_log: stdout or IO):
self.loglevel = loglevel
self.place_to_log = place_to_log
def debug(self, message):
if self.loglevel > LogLevels.DEBUG: return
self.place_to_log.write(f"[DEBUG] <{time()}> {message}\n")
def info(self, message):
if self.loglevel > LogLevels.INFO: return
self.place_to_log.write(f"[INFO] <{time()}> {message}\n")
def warning(self, message):
if self.loglevel > LogLevels.WARNING: return
self.place_to_log.write(f"[WARNING] <{time()}> {message}\n")
def error(self, message):
if self.loglevel > LogLevels.ERROR: return
self.place_to_log.write(f"[ERROR] <{time}> {message}\n")

120
src/services/worker.py Normal file
View File

@ -0,0 +1,120 @@
import asyncio
import json
import sys
import bs4
import requests
from src.dataclasses.loglevels import LogLevels
from src.dataclasses.task import RequestTsInfoTask
from src.services.dummy_broker import Broker
from src.services.logger import Logger
class Worker:
"""
Worker is a class that fetches tasks queue from a broker and executes them in order, given in the tasks_queue list.
"""
def __init__(self):
self.broker = Broker()
self.logger = Logger(LogLevels.DEBUG, sys.stdout)
async def process(self):
"""
Asynchronous method of a Worker class that polls tasks from the Broker and works on them.
:return:
"""
self.logger.info("Worker started")
while True:
task = self.broker.get_task()
if not task:
sleep_for = 10
self.logger.info(f"No tasks for now. Sleeping for {sleep_for} seconds")
await asyncio.sleep(sleep_for)
continue
self.logger.debug(f"Got a task with type {type(task).__name__}. Working on it.")
match type(task).__name__:
case RequestTsInfoTask.__name__:
await self.task_request_ts(task)
async def task_request_ts(self, task: RequestTsInfoTask):
"""
Method used to fetch and parse data from https://nsis.ru/products/osago/check/
:param RequestTsInfoTask task:
:return:
"""
headers = {
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "multipart/form-data; boundary=---------------------------330424154228665440354056616977"
}
data = f'-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="licenseplate"\r\n\r\n{task.license_plate}\r\n-----------------------------330424154228665440354056616977\r\nContent-Disposition: form-data; name="requestdate"\r\n\r\n{task.prior_to_date}'
with requests.Session() as s:
response = s.post('https://nsis.ru/handle-form/1314895756519276544/', headers=headers, data=data)
response_text = response.text
response_json = json.loads(response_text)
# For some reason, in backend's response there is huge (4MBs) field 'random_str' that contains a heckin' random string.
response_json["random_str"] = ""
self.logger.debug(f"First stage response (JSON): {response_json}")
if not response_json["isSuccess"]:
self.logger.error("Request to https://nsis.ru/handle-form/1314895756519276544 has failed. Details in [DEBUG].")
self.logger.debug(response.reason)
process_id = response_json["data"]["processId"]
form_code = response_json["data"]["formCode"]
# TODO: find optimal time for request completion
await asyncio.sleep(7)
response = s.get(f"https://nsis.ru/api/v1/status/{process_id}/?formCode={form_code}", headers=headers)
response_text = response.text
response_json = json.loads(response_text)
response_json["random_str"] = ""
self.logger.debug(f"Second stage response (JSON): ${response_json}")
html = response_json["modals"]["html"]
soup = bs4.BeautifulSoup(html)
log_header = f"(LP: {task.license_plate}, Date: {task.prior_to_date})"
if soup.find("div", attrs={'id': 'modal-policy-not-found'}):
self.logger.debug(f"{log_header} Modal policy not found for request {data} (processId: {process_id})")
self.logger.info(f"{log_header} Modal policy was not found.")
return
if not soup.find('div', attrs={'class': 'modal'}):
self.logger.error(f"{log_header} Modal policy class was not found in response. Details in [DEBUG].")
self.logger.debug(f"{log_header} Modal policy not found. Data: {data} (processId: {process_id}). HTML from response: {html}")
return
self.logger.info(f"{log_header} Modal policy found.")
"""
Should contain 9 elements:
1. Серия полиса,
2. Номер полиса,
3. Статус договора ОСАГО,
4. Период использования, (it is a dd element with an extra class 'dataList__value--isChildren' and it contains span with actual data.
5. Марка и модель ТС,
6. Идентификационный номер транспортного средства,
7. Государственный регистрационный знак, (it is partially hidden, should use one from the request.
8. Страховая компания,
9. Расширение на территорию Республики Беларусь
"""
values = soup.findAll('dd', attrs={'class': 'dataList__value'})
if len(values) != 9:
self.logger.error(f"{log_header} The parser found {len(values)} elements, but should find 9. It could be that API has changed. Additional info is present in [DEBUG]")
self.logger.debug(f"{log_header} Array of found element {values}")
return
header_len = len(log_header)
self.logger.info(f"\n--=={log_header}==--\n"
f"Данные на {task.prior_to_date}\n"
f"Серия полиса: {values[0].text}\n"
f"Номер полиса: {values[1].text}\n"
f"Статус договора ОСАГО: {values[2].text}\n"
f"Период использования: {values[3].find('span').text}\n"
f"Марка и модель ТС: {values[4].text}\n"
f"Идентификационный номер транспортного средства: {values[5].text}\n"
f"Государственный регистрационный знак: {task.license_plate}\n"
f"Страховая компания: {values[7].text}\n"
f"Расширение на территорию Республики Беларусь: {values[8].text}\n"
f"--=={'*' * header_len}==--")

0
tests/__init__.py Normal file
View File