Psing login
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 ActorsPsing login
axxsh/psing-login
Psing login
.actor/Dockerfile
1# Use Apify base image with Python and Playwright
2FROM apify/actor-python-playwright
3
4# Copy all source code to the default working directory
5COPY ./src /app
6
7# Install Python dependencies
8RUN pip install requests
9
10# Run the actor script
11CMD ["python", "/app/main.py"]
.actor/actor.json
1{
2 "name": "my-actor",
3 "version": "0.1",
4 "description": "This is my Apify actor for login automation.",
5 "actorSpecification": 1,
6 "input": "./input_schema.json",
7 "main": "src/main.py"
8}
.actor/input_schema.json
1{
2 "schemaVersion": 1,
3 "title": "My Actor Input Schema",
4 "type": "object",
5 "properties": {
6 "start_url": {
7 "type": "string",
8 "title": "Start URL",
9 "description": "The URL to start the scraping process.",
10 "editor": "textfield"
11 },
12 "company_id": {
13 "type": "string",
14 "title": "Company ID",
15 "description": "ID of the company.",
16 "editor": "textfield"
17 },
18 "username": {
19 "type": "string",
20 "title": "Username",
21 "description": "Username for login.",
22 "editor": "textfield"
23 },
24 "password": {
25 "type": "string",
26 "title": "Password",
27 "description": "Password for login.",
28 "editor": "textfield"
29 },
30 "patient_id": {
31 "type": "string",
32 "title": "Patient ID",
33 "description": "ID of the patient.",
34 "editor": "textfield"
35 },
36 "type_id": {
37 "type": "string",
38 "title": "Type ID",
39 "description": "ID for the appointment type.",
40 "editor": "textfield"
41 },
42 "user_id": {
43 "type": "string",
44 "title": "User ID",
45 "description": "ID of the user making the appointment.",
46 "editor": "textfield"
47 },
48 "reason": {
49 "type": "string",
50 "title": "Reason",
51 "description": "Reason for the appointment.",
52 "editor": "textfield"
53 },
54 "room": {
55 "type": "string",
56 "title": "Room",
57 "description": "Room number for the appointment.",
58 "editor": "textfield"
59 },
60 "appointment_date": {
61 "type": "string",
62 "title": "Appointment Date",
63 "description": "Date of the appointment.",
64 "editor": "datepicker"
65 },
66 "time": {
67 "type": "string",
68 "title": "Appointment Start Time",
69 "description": "Start time of the appointment.",
70 "editor": "textfield"
71 },
72 "time_end": {
73 "type": "string",
74 "title": "Appointment End Time",
75 "description": "End time of the appointment.",
76 "editor": "textfield"
77 },
78 "useRealEndTime": {
79 "type": "boolean",
80 "title": "Use Real End Time",
81 "description": "Whether to use the real end time for the appointment.",
82 "editor": "checkbox",
83 "default": true
84 }
85 },
86 "required": ["start_url", "username", "password", "patient_id", "type_id", "user_id", "reason", "room", "appointment_date", "time", "time_end", "useRealEndTime"]
87}
src/__main__.py
1import asyncio
2from .main import main
3
4# Execute the Actor entry point
5asyncio.run(main())
src/main.py
1import logging
2import json
3import asyncio
4import requests
5from playwright.async_api import async_playwright
6from apify import Actor # Import the Actor module
7
8logging.basicConfig(level=logging.INFO)
9
10async def main():
11 # Initialize the actor
12 await Actor.init()
13
14 # Load input parameters from Apify input
15 actor_input = await Actor.get_input() or {}
16
17 # Log the input data for debugging
18 logging.info(f'Input data: {actor_input}')
19
20 # Extract input parameters from the input JSON
21 start_url = actor_input.get('start_url')
22 company_id = actor_input.get('company_id')
23 username = actor_input.get('username')
24 password = actor_input.get('password')
25 appointment_details = {
26 'patient_id': actor_input.get('patient_id'),
27 'type_id': actor_input.get('type_id'),
28 'user_id': actor_input.get('user_id'),
29 'reason': actor_input.get('reason'),
30 'room': actor_input.get('room'),
31 'appointment_date': actor_input.get('appointment_date'),
32 'time': actor_input.get('time'),
33 'time_end': actor_input.get('time_end'),
34 'useRealEndTime': actor_input.get('useRealEndTime')
35 }
36
37 # Log extracted appointment details
38 logging.info(f'Appointment Details: {appointment_details}')
39
40 # Ensure all input fields have values, raise an error if any critical field is missing
41 if not all([start_url, company_id, username, password, appointment_details['patient_id'],
42 appointment_details['type_id'], appointment_details['user_id'],
43 appointment_details['reason'], appointment_details['room'],
44 appointment_details['appointment_date'], appointment_details['time'],
45 appointment_details['time_end']]):
46 logging.error("Missing required input fields!")
47 return
48
49 async with async_playwright() as p:
50 browser = await p.chromium.launch(headless=True)
51 context = await browser.new_context()
52 page = await context.new_page()
53
54 # Initialize variables to hold request headers
55 sec_ch_ua = None
56 sec_ch_ua_mobile = None
57
58 # Capture request headers when a request is made
59 def extract_headers(headers):
60 nonlocal sec_ch_ua, sec_ch_ua_mobile
61 sec_ch_ua = headers.get('sec-ch-ua')
62 sec_ch_ua_mobile = headers.get('sec-ch-ua-mobile')
63
64 page.on('request', lambda request: extract_headers(request.headers))
65
66 logging.info(f'Navigating to {start_url}...')
67 await page.goto(start_url)
68
69 # Fill in the login form
70 await page.fill('#company_id', company_id)
71 await page.fill('#username', username)
72 await page.fill('#password', password)
73 await page.click('#btnLogin')
74
75 # Wait for navigation to the dashboard
76 await page.wait_for_url('**/dashboard', timeout=15000)
77 logging.info('Login successful! On the dashboard page.')
78
79 # Extract cookies
80 cookies = await context.cookies()
81 logging.info(f'Cookies: {cookies}')
82 cookie_string = "; ".join([f"{cookie['name']}={cookie['value']}" for cookie in cookies])
83 logging.info(f'Cookie String: {cookie_string}')
84
85 # Extract XSRF token
86 xsrf_token = next((cookie['value'] for cookie in cookies if cookie['name'] == 'XSRF-TOKEN'), None)
87 logging.info(f'XSRF Token: {xsrf_token}')
88
89 # Extract user agent
90 user_agent = await page.evaluate("() => navigator.userAgent")
91 logging.info(f'User Agent: {user_agent}')
92
93 # Log sec-ch-ua and sec-ch-ua-mobile
94 logging.info(f'SEC-CH-UA: {sec_ch_ua}')
95 logging.info(f'SEC-CH-UA-Mobile: {sec_ch_ua_mobile}')
96
97 # Prepare the request headers dynamically
98 request_url = 'https://us.idexxneo.com/appointments/create'
99 headers = {
100 'accept': 'application/json, text/plain, */*',
101 'accept-encoding': 'gzip, deflate, br, zstd',
102 'accept-language': 'en-GB,en;q=0.9',
103 'cookie': cookie_string,
104 'origin': 'https://us.idexxneo.com',
105 'referer': 'https://us.idexxneo.com/schedule/appointments/new?date=' + appointment_details['appointment_date'] + '&time=' + appointment_details['time'],
106 'sec-ch-ua': sec_ch_ua if sec_ch_ua else '',
107 'sec-ch-ua-mobile': sec_ch_ua_mobile if sec_ch_ua_mobile else '',
108 'sec-fetch-dest': 'empty',
109 'sec-fetch-mode': 'cors',
110 'sec-fetch-site': 'same-origin',
111 'sec-gpc': '1',
112 'user-agent': user_agent,
113 'x-neo-core-version': '87.0.0',
114 'x-xsrf-token': xsrf_token
115 }
116
117 # Adjust form data to use 'files' for multipart data
118 files = {
119 'patient_id': (None, appointment_details['patient_id']),
120 'type_id': (None, appointment_details['type_id']),
121 'user_id': (None, appointment_details['user_id']),
122 'reason': (None, appointment_details['reason']),
123 'room': (None, appointment_details['room']),
124 'appointment_date': (None, appointment_details['appointment_date']),
125 'time': (None, appointment_details['time']),
126 'time_end': (None, appointment_details['time_end']),
127 'useRealEndTime': (None, str(appointment_details['useRealEndTime']).lower())
128 }
129
130 # Send the POST request
131 response = requests.post(request_url, headers=headers, files=files)
132
133 # Print the response
134 logging.info(f'Status Code: {response.status_code}')
135 logging.info(f'Response: {response.text}')
136
137 await browser.close()
138
139if __name__ == '__main__':
140 asyncio.run(main())
.dockerignore
1.git
2.mise.toml
3.nvim.lua
4storage
5
6# The rest is copied from https://github.com/github/gitignore/blob/main/Python.gitignore
7
8# Byte-compiled / optimized / DLL files
9__pycache__/
10*.py[cod]
11*$py.class
12
13# C extensions
14*.so
15
16# Distribution / packaging
17.Python
18build/
19develop-eggs/
20dist/
21downloads/
22eggs/
23.eggs/
24lib/
25lib64/
26parts/
27sdist/
28var/
29wheels/
30share/python-wheels/
31*.egg-info/
32.installed.cfg
33*.egg
34MANIFEST
35
36# PyInstaller
37# Usually these files are written by a python script from a template
38# before PyInstaller builds the exe, so as to inject date/other infos into it.
39*.manifest
40*.spec
41
42# Installer logs
43pip-log.txt
44pip-delete-this-directory.txt
45
46# Unit test / coverage reports
47htmlcov/
48.tox/
49.nox/
50.coverage
51.coverage.*
52.cache
53nosetests.xml
54coverage.xml
55*.cover
56*.py,cover
57.hypothesis/
58.pytest_cache/
59cover/
60
61# Translations
62*.mo
63*.pot
64
65# Django stuff:
66*.log
67local_settings.py
68db.sqlite3
69db.sqlite3-journal
70
71# Flask stuff:
72instance/
73.webassets-cache
74
75# Scrapy stuff:
76.scrapy
77
78# Sphinx documentation
79docs/_build/
80
81# PyBuilder
82.pybuilder/
83target/
84
85# Jupyter Notebook
86.ipynb_checkpoints
87
88# IPython
89profile_default/
90ipython_config.py
91
92# pyenv
93# For a library or package, you might want to ignore these files since the code is
94# intended to run in multiple environments; otherwise, check them in:
95.python-version
96
97# pdm
98# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
99#pdm.lock
100# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
101# in version control.
102# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
103.pdm.toml
104.pdm-python
105.pdm-build/
106
107# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
108__pypackages__/
109
110# Celery stuff
111celerybeat-schedule
112celerybeat.pid
113
114# SageMath parsed files
115*.sage.py
116
117# Environments
118.env
119.venv
120env/
121venv/
122ENV/
123env.bak/
124venv.bak/
125
126# Spyder project settings
127.spyderproject
128.spyproject
129
130# Rope project settings
131.ropeproject
132
133# mkdocs documentation
134/site
135
136# mypy
137.mypy_cache/
138.dmypy.json
139dmypy.json
140
141# Pyre type checker
142.pyre/
143
144# pytype static type analyzer
145.pytype/
146
147# Cython debug symbols
148cython_debug/
149
150# PyCharm
151# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
152# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
153# and can be added to the global gitignore or merged into this file. For a more nuclear
154# option (not recommended) you can uncomment the following to ignore the entire idea folder.
155.idea/
.gitignore
1.mise.toml
2.nvim.lua
3storage
4
5# The rest is copied from https://github.com/github/gitignore/blob/main/Python.gitignore
6
7# Byte-compiled / optimized / DLL files
8__pycache__/
9*.py[cod]
10*$py.class
11
12# C extensions
13*.so
14
15# Distribution / packaging
16.Python
17build/
18develop-eggs/
19dist/
20downloads/
21eggs/
22.eggs/
23lib/
24lib64/
25parts/
26sdist/
27var/
28wheels/
29share/python-wheels/
30*.egg-info/
31.installed.cfg
32*.egg
33MANIFEST
34
35# PyInstaller
36# Usually these files are written by a python script from a template
37# before PyInstaller builds the exe, so as to inject date/other infos into it.
38*.manifest
39*.spec
40
41# Installer logs
42pip-log.txt
43pip-delete-this-directory.txt
44
45# Unit test / coverage reports
46htmlcov/
47.tox/
48.nox/
49.coverage
50.coverage.*
51.cache
52nosetests.xml
53coverage.xml
54*.cover
55*.py,cover
56.hypothesis/
57.pytest_cache/
58cover/
59
60# Translations
61*.mo
62*.pot
63
64# Django stuff:
65*.log
66local_settings.py
67db.sqlite3
68db.sqlite3-journal
69
70# Flask stuff:
71instance/
72.webassets-cache
73
74# Scrapy stuff:
75.scrapy
76
77# Sphinx documentation
78docs/_build/
79
80# PyBuilder
81.pybuilder/
82target/
83
84# Jupyter Notebook
85.ipynb_checkpoints
86
87# IPython
88profile_default/
89ipython_config.py
90
91# pyenv
92# For a library or package, you might want to ignore these files since the code is
93# intended to run in multiple environments; otherwise, check them in:
94.python-version
95
96# pdm
97# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
98#pdm.lock
99# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
100# in version control.
101# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
102.pdm.toml
103.pdm-python
104.pdm-build/
105
106# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
107__pypackages__/
108
109# Celery stuff
110celerybeat-schedule
111celerybeat.pid
112
113# SageMath parsed files
114*.sage.py
115
116# Environments
117.env
118.venv
119env/
120venv/
121ENV/
122env.bak/
123venv.bak/
124
125# Spyder project settings
126.spyderproject
127.spyproject
128
129# Rope project settings
130.ropeproject
131
132# mkdocs documentation
133/site
134
135# mypy
136.mypy_cache/
137.dmypy.json
138dmypy.json
139
140# Pyre type checker
141.pyre/
142
143# pytype static type analyzer
144.pytype/
145
146# Cython debug symbols
147cython_debug/
148
149# PyCharm
150# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
151# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
152# and can be added to the global gitignore or merged into this file. For a more nuclear
153# option (not recommended) you can uncomment the following to ignore the entire idea folder.
154.idea/
real.py
1from apify import Actor
2from crawlee.playwright_crawler import PlaywrightCrawler, PlaywrightCrawlingContext
3
4async def main() -> None:
5 """Main entry point for the Apify Actor."""
6 async with Actor:
7 actor_input = await Actor.get_input() or {}
8 start_urls = [url.get('url') for url in actor_input.get('start_urls', [{'url': 'https://us.idexxneo.com/login?'}])]
9
10 if not start_urls:
11 Actor.log.info('No start URLs specified in Actor input, exiting...')
12 await Actor.exit()
13
14 crawler = PlaywrightCrawler(
15 max_requests_per_crawl=1, # We only need to handle one request for the login
16 headless=True,
17 )
18
19 @crawler.router.default_handler
20 async def request_handler(context: PlaywrightCrawlingContext) -> None:
21 url = context.request.url
22 Actor.log.info(f'Navigating to {url}...')
23
24 # Navigate to the login page
25 await context.page.goto(url)
26
27 # Perform login actions
28 await context.page.fill('//*[@id="company_id"]', '7880')
29 await context.page.fill('//*[@id="username"]', 'PSingh')
30 await context.page.fill('//*[@id="password"]', 'Temppass1234!')
31
32 # Click the login button
33 await context.page.click('//*[@id="btnLogin"]')
34
35 # Wait for the page to load after login
36 await context.page.wait_for_load_state('networkidle') # Wait until there are no more network connections for at least 500 ms
37
38 # After logging in, you can extract data or navigate further
39 Actor.log.info('Login successful!')
40
41 # Example: Extracting data after login (you can customize this)
42 data = {
43 'url': context.request.url,
44 'title': await context.page.title(),
45 }
46 await context.push_data(data)
47
48 await crawler.run(start_urls)
49
50if __name__ == '__main__':
51 import asyncio
52 asyncio.run(main())
requirements.txt
1# Feel free to add your Python dependencies below. For formatting guidelines, see:
2# https://pip.pypa.io/en/latest/reference/requirements-file-format/
3
4apify == 2.0.0
5crawlee[playwright]
Developer
Maintained by Community
Categories