Humana Book of Business to CSV Extractor
Go to Store
This Actor is unavailable because the developer has decided to deprecate it. Would you like to try a similar Actor instead?
See alternative ActorsHumana Book of Business to CSV Extractor
medicare_tools/humana-book-of-business-to-csv-extractor
.actor/Dockerfile
1# First, specify the base Docker image.
2# You can see the Docker images from Apify at https://hub.docker.com/r/apify/.
3# You can also use any other image from Docker Hub.
4FROM apify/actor-python-selenium:3.11
5
6# Second, copy just requirements.txt into the Actor image,
7# since it should be the only file that affects the dependency install in the next step,
8# in order to speed up the build
9COPY requirements.txt ./
10
11# Install the packages specified in requirements.txt,
12# Print the installed Python version, pip version
13# and all installed packages with their versions for debugging
14RUN echo "Python version:" \
15 && python --version \
16 && echo "Pip version:" \
17 && pip --version \
18 && echo "Installing dependencies:" \
19 && pip install -r requirements.txt \
20 && echo "All installed Python packages:" \
21 && pip freeze
22
23# Next, copy the remaining files and directories with the source code.
24# Since we do this after installing the dependencies, quick build will be really fast
25# for most source file changes.
26COPY . ./
27
28# Use compileall to ensure the runnability of the Actor Python code.
29RUN python3 -m compileall -q .
30
31# Specify how to launch the source code of your Actor.
32# By default, the "python3 -m src" command is run
33CMD ["python3", "-m", "src"]
.actor/actor.json
1{
2 "actorSpecification": 1,
3 "name": "MemberInformation-actor",
4 "title": "Data Extraction for Member Information",
5 "description": "Extracts member information using provided data.",
6 "version": "0.1",
7 "meta": {
8 "templateId": "python-dictionary"
9 },
10 "input": "./input_schema.json",
11 "dockerfile": "./Dockerfile",
12 "storages": {
13 "dataset": {
14 "actorSpecification": 1,
15 "title": "Member Information Data",
16 "views": {
17 "member": {
18 "title": "Member Information Data",
19 "transformation": {
20 "fields": [
21 "First Name",
22 "Last Name",
23 "MBI",
24 "DOB",
25 "Medicaid #",
26 "LIS",
27 "Carrier",
28 "Carrier Member #",
29 "Status",
30 "Plan Type",
31 "Contract #",
32 "Plan Name",
33 "Monthly premium",
34 "PCP on file",
35 "Phone",
36 "Email",
37 "Address Line 1",
38 "Address Line 2",
39 "City",
40 "State",
41 "Zip",
42 "County",
43 "Application ID",
44 "Election Code",
45 "Application Date",
46 "Approval Date",
47 "Effective Date",
48 "Termination Date",
49 "Termination Reason",
50 "Writing Agent",
51 "Writing Agent NPN",
52 "Agent Writing ID"
53 ]
54 },
55 "display": {
56 "component": "table",
57 "properties": {
58 "First Name": {
59 "label": "First Name",
60 "format": "text"
61 },
62 "Last Name": {
63 "label": "Last Name",
64 "format": "text"
65 },
66 "MBI": {
67 "label": "MBI",
68 "format": "text"
69 },
70 "DOB": {
71 "label": "Date of Birth",
72 "format": "text"
73 },
74 "Medicaid #": {
75 "label": "Medicaid Number",
76 "format": "text"
77 },
78 "LIS": {
79 "label": "LIS Indicator",
80 "format": "text"
81 },
82 "Carrier": {
83 "label": "Carrier",
84 "format": "text"
85 },
86 "Carrier Member #": {
87 "label": "Carrier Member Number",
88 "format": "text"
89 },
90 "Status": {
91 "label": "Status",
92 "format": "text"
93 },
94 "Plan Type": {
95 "label": "Plan Type",
96 "format": "text"
97 },
98 "Contract #": {
99 "label": "Contract Number",
100 "format": "text"
101 },
102 "Plan Name": {
103 "label": "Plan Name",
104 "format": "text"
105 },
106 "Monthly premium": {
107 "label": "Monthly Premium",
108 "format": "text"
109 },
110 "PCP on file": {
111 "label": "Primary Care Physician on File",
112 "format": "text"
113 },
114 "Phone": {
115 "label": "Phone",
116 "format": "text"
117 },
118 "Email": {
119 "label": "Email",
120 "format": "text"
121 },
122 "Address Line 1": {
123 "label": "Address Line 1",
124 "format": "text"
125 },
126 "Address Line 2": {
127 "label": "Address Line 2",
128 "format": "text"
129 },
130 "City": {
131 "label": "City",
132 "format": "text"
133 },
134 "State": {
135 "label": "State",
136 "format": "text"
137 },
138 "Zip": {
139 "label": "Zip",
140 "format": "text"
141 },
142 "County": {
143 "label": "County",
144 "format": "text"
145 },
146 "Application ID": {
147 "label": "Application ID",
148 "format": "text"
149 },
150 "Election Code": {
151 "label": "Election Code",
152 "format": "text"
153 },
154 "Application Date": {
155 "label": "Application Date",
156 "format": "text"
157 },
158 "Approval Date": {
159 "label": "Approval Date",
160 "format": "text"
161 },
162 "Effective Date": {
163 "label": "Effective Date",
164 "format": "text"
165 },
166 "Termination Date": {
167 "label": "Termination Date",
168 "format": "text"
169 },
170 "Termination Reason": {
171 "label": "Termination Reason",
172 "format": "text"
173 },
174 "Writing Agent": {
175 "label": "Writing Agent",
176 "format": "text"
177 },
178 "Writing Agent NPN": {
179 "label": "Writing Agent NPN",
180 "format": "text"
181 },
182 "Agent Writing ID": {
183 "label": "Agent Writing ID",
184 "format": "text"
185 }
186 }
187 }
188 }
189 }
190 }
191 }
192}
.actor/input_schema.json
1{
2 "title": "HumanaScraper",
3 "type": "object",
4 "schemaVersion": 1,
5 "properties": {
6 "username": {
7 "title": "Username/Email",
8 "type": "string",
9 "description": "Enter the username or email address used for login.",
10 "editor": "textfield"
11 },
12 "password": {
13 "title": "Password",
14 "type": "string",
15 "description": "Enter the password for login.",
16 "isSecret": true,
17 "editor": "textfield"
18 }
19},
20 "required": ["username", "password"]
21}
src/__main__.py
1"""
2This module serves as the entry point for executing the Apify Actor. It handles the configuration of logging
3settings. The `main()` coroutine is then executed using `asyncio.run()`.
4
5Feel free to modify this file to suit your specific needs.
6"""
7
8import asyncio
9import logging
10
11from apify.log import ActorLogFormatter
12
13from .main import main
14
15# Configure loggers
16handler = logging.StreamHandler()
17handler.setFormatter(ActorLogFormatter())
18
19apify_client_logger = logging.getLogger('apify_client')
20apify_client_logger.setLevel(logging.INFO)
21apify_client_logger.addHandler(handler)
22
23apify_logger = logging.getLogger('apify')
24apify_logger.setLevel(logging.DEBUG)
25apify_logger.addHandler(handler)
26
27# Execute the Actor main coroutine
28asyncio.run(main())
src/main.py
1from urllib.parse import urljoin
2from selenium import webdriver
3from selenium.webdriver.chrome.options import Options as ChromeOptions
4from selenium.webdriver.common.by import By
5from apify import Actor
6import asyncio
7import time
8import random
9from selenium.webdriver.support.ui import Select
10from selenium.webdriver.common.keys import Keys
11from selenium.webdriver.common.by import By
12import requests
13from bs4 import BeautifulSoup as bs
14import csv
15import pandas as pd
16from tqdm import tqdm
17from datetime import datetime, timedelta
18import dateutil.relativedelta
19from seleniumbase import Driver
20from concurrent.futures import ThreadPoolExecutor
21
22
23async def login(browser, username, password):
24 browser.get('https://account.humana.com/')
25 time.sleep(random.uniform(4, 5))
26 # send npi
27 browser.find_element(By.CSS_SELECTOR, 'input[name="Username"]').send_keys(username)
28 # send password
29 browser.find_element(By.CSS_SELECTOR, 'input[name="Password"]').send_keys(password)
30 # click login
31 browser.find_element(By.CSS_SELECTOR, 'button[type="submit"]').click()
32 time.sleep(random.uniform(15, 20))
33 try:
34 browser.find_element(By.XPATH, '//*[@id="multiPortalAccessForm"]/ul/li[2]/button').click()
35 time.sleep(random.uniform(10,15))
36 except:
37 pass
38 try:
39 browser.find_element(By.XPATH, '//a[contains(text(),"Vantage")]').click()
40 time.sleep(2)
41 except:
42 pass
43 # browse.refresh()
44 # click p with View All Customers text
45 browser.find_element(By.XPATH, '//p[text()="View All Customers"]').click()
46 # browser.get("https://agentportal.humana.com/Vantage/apps/index.html?agenthome=-1#!/businessCenter")
47 time.sleep(random.uniform(20,30))
48 cookies = browser.get_cookies()
49 cookies = {cookie['name']: cookie['value'] for cookie in cookies}
50 return cookies
51
52
53async def get_list(cookies, headers):
54 json_data = {
55 'filters': {
56 'dateFilter': None,
57 'filterValuesIds': [],
58 },
59 'insightId': 'all',
60 'resultPaging': {
61 'amount': 50,
62 'page': 0,
63 },
64 'resultSort': {
65 'columnId': 49,
66 'order': 'asc',
67 },
68 }
69
70 response = requests.post(
71 'https://agentportal.humana.com/Vantage/api/businesscenter/search-policies-and-applications',
72 cookies=cookies,
73 headers=headers,
74 json=json_data,
75 )
76 # print(response.text)
77 data = response.json()
78 total = data['totalRecords']
79 total_pages = total//50+1
80 list_data = data['records']
81 for i in range(1, total_pages):
82 json_data['resultPaging']['page'] = i
83 response = requests.post(
84 'https://agentportal.humana.com/Vantage/api/businesscenter/search-policies-and-applications',
85 cookies=cookies,
86 headers=headers,
87 json=json_data,
88 )
89 data = response.json()
90 list_data += data['records']
91 return list_data
92
93
94async def process(full_data):
95 memberInformation = full_data['memberInformation']
96 otherPolicyInformation = full_data['otherPolicyInformation']
97 policyInformation = full_data['policyInformation']
98 compensatedAgentInfo = full_data['compensatedAgentInfo']
99 memberInformation_dict = {
100 "First Name": memberInformation['mbrFirstName'],
101 "Last Name": memberInformation['mbrLastName'] + memberInformation['mbrMiddleInit'],
102 "MBI": memberInformation['medicareId'],
103 "DOB": datetime.strptime(memberInformation['birthDate'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") if memberInformation['birthDate'] is not None else None,
104 "Medicaid #": memberInformation['medicaidId'],
105 "LIS": memberInformation['lisIndicator'],
106 "Carrier":"Humana",
107 "Carrier Member #":otherPolicyInformation[0]['humanaID'],
108 "Status": otherPolicyInformation[0]['status'],
109 "Plan Type": otherPolicyInformation[0]['planType'],
110 "Contract #": otherPolicyInformation[0]['product'],
111 "Plan Name": otherPolicyInformation[0]['planAltDesc'],
112 "Monthly premium":"-",
113 "PCP on file": policyInformation['mbrName'],
114 "Phone": memberInformation['mbrPrimPhone'],
115 "Email": memberInformation['mbrEmail'],
116 "Address Line 1": memberInformation['address']['residentAddressLine1'],
117 "Address Line 1": memberInformation['address']['residentAddressLine2'],
118 "City": memberInformation['address']['residentCityName'],
119 "State": memberInformation['address']['residentStateCode'],
120 "Zip": memberInformation['address']['residentZipCode'],
121 "County": memberInformation['address']['residentCountyName'],
122 "Application ID": policyInformation['applicationId'],
123 "Election Code": policyInformation['electionTypeCode'],
124 "Application Date": datetime.strptime(policyInformation['signatureDate'], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") if memberInformation['birthDate'] is not None else None,
125 "Approval Date": "-",
126 "Effective Date": datetime.strptime(policyInformation['covEffDate'],"%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") if memberInformation['birthDate'] is not None else None,
127 "Termination Reason":"-",
128 "Writing Agent": otherPolicyInformation[0]['writingAgent'],
129 "Writing Agent NPN": otherPolicyInformation[0]['npn'],
130
131 }
132
133 try:
134 memberInformation_dict["Termination Date"] = datetime.strptime(policyInformation['covTermDate'],"%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y")
135 except:
136 memberInformation_dict["Termination Date"] = ''
137
138 try:
139 memberInformation_dict["Agent Writing ID"] = compensatedAgentInfo['aorSan']
140 except:
141 memberInformation_dict["Agent Writing ID"] = ''
142 return memberInformation_dict
143
144
145async def get_details(cookies, headers, d):
146 today = datetime.today()
147 month = today.month
148 year = today.year
149 day = today.day
150 url = f"https://agentportal.humana.com/Vantage/api/businesscenter/member?recordId={d['id']}&salesMemKey={d['salesMemKey']}&modifiedDTime={year}%2F{month}%2F{day}T00:00:00Z"
151 response = requests.get(
152 url,
153 cookies=cookies,
154 headers=headers,
155 )
156 full_data = response.json()
157 memberInformation_dict = await process(full_data)
158 print(f"Got Data for {d['id']}")
159 await Actor.push_data(memberInformation_dict)
160 return memberInformation_dict
161
162async def main():
163 async with Actor:
164 # Read the Actor input
165 actor_input = await Actor.get_input() or {}
166 username = actor_input.get("username")
167 password = actor_input.get("password")
168 # check both start_date and end_date are not empty
169 # Launch a new Selenium Chrome WebDriver
170 Actor.log.info('Launching Chrome WebDriver...')
171 # chrome_options = ChromeOptions()
172 # if Actor.config.headless:
173 # chrome_options.add_argument('--headless')
174 # chrome_options.add_argument('--no-sandbox')
175 # chrome_options.add_argument('--disable-dev-shm-usage')
176 # chrome_options.add_argument('--window-size=1920,1080')
177 # browser = webdriver.Chrome(options=chrome_options)
178 browser = Driver(uc=True, headless=True)
179 # ruh the login function
180 cookies = await login(browser, username, password)
181 Actor.log.info("Logged In!")
182 headers = {
183 'Accept': 'application/json, text/plain, */*',
184 'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8',
185 'Authorization': 'Basic VmFudGFnZVdlYkFwcDpwN1JFdmVkIzE=',
186 'Connection': 'keep-alive',
187 'Content-Type': 'application/json',
188 'Origin': 'https://agentportal.humana.com',
189 'Referer': 'https://agentportal.humana.com/Vantage/apps/index.html?agenthome=-1',
190 'Sec-Fetch-Dest': 'empty',
191 'Sec-Fetch-Mode': 'cors',
192 'Sec-Fetch-Site': 'same-origin',
193 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
194 'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
195 'sec-ch-ua-mobile': '?0',
196 'sec-ch-ua-platform': '"Windows"',
197 }
198 headers['x-dtpc'] = cookies['dtPC']
199 list_data = await get_list(cookies, headers)
200 Actor.log.info("Getting Data....")
201 csv_df = []
202 with ThreadPoolExecutor(max_workers=5) as executor:
203 tasks = [get_details(cookies, headers, d) for d in tqdm(list_data)]
204 await asyncio.gather(*tasks)
205 Actor.log.info("Completed.")
206 browser.quit()
207if __name__ == "__main__":
208 asyncio.run(main())
.dockerignore
1# configurations
2.idea
3
4# crawlee and apify storage folders
5apify_storage
6crawlee_storage
7storage
8
9# installed files
10.venv
11
12# git folder
13.git
.editorconfig
1root = true
2
3[*]
4indent_style = space
5indent_size = 4
6charset = utf-8
7trim_trailing_whitespace = true
8insert_final_newline = true
9end_of_line = lf
.gitignore
1# This file tells Git which files shouldn't be added to source control
2
3.idea
4.DS_Store
5
6apify_storage
7storage
8
9.venv/
10.env/
11__pypackages__
12dist/
13build/
14*.egg-info/
15*.egg
16
17__pycache__
18
19.mypy_cache
20.dmypy.json
21dmypy.json
22.pytest_cache
23.ruff_cache
24
25.scrapy
26*.log
requirements.txt
1# Add your dependencies here.
2# See https://pip.pypa.io/en/latest/reference/requirements-file-format/
3# for how to format them
4apify ~= 1.2.0
5selenium ~= 4.14.0
6seleniumbase
7tqdm
8bs4
9pandas
Developer
Maintained by Community
Categories