-
-
Save yaojialyu/0c59c23d84585cc6e889e394d928a164 to your computer and use it in GitHub Desktop.
# -*- coding: utf8 -*- | |
import time | |
import json | |
import random | |
import platform | |
from datetime import datetime | |
import requests | |
from selenium import webdriver | |
from selenium.webdriver.support import expected_conditions as EC | |
from selenium.webdriver.support.ui import WebDriverWait as Wait | |
from selenium.webdriver.common.by import By | |
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities | |
USERNAME = '<username>' | |
PASSWORD = '<pwd>' | |
SCHEDULE = '<schedule number>' | |
PUSH_TOKEN = '<my push token>' | |
PUSH_USER = '<my push user>' | |
MY_SCHEDULE_DATE = "<current date>" # 2020-12-02 | |
#MY_CONDITION = lambda month,day: int(month) == 11 or (int(month) == 12 and int(day) <=5) | |
MY_CONDITION = lambda month,day: int(month) == 11 and int(day) >= 5 | |
SLEEP_TIME = 5 # recheck time interval | |
DATE_URL = "https://ais.usvisa-info.com/en-ec/niv/schedule/%s/appointment/days/108.json?appointments[expedite]=false" % SCHEDULE | |
TIME_URL = "https://ais.usvisa-info.com/en-ec/niv/schedule/%s/appointment/times/108.json?date=%%s&appointments[expedite]=false" % SCHEDULE | |
APPOINTMENT_URL = "https://ais.usvisa-info.com/en-ec/niv/schedule/%s/appointment" % SCHEDULE | |
HUB_ADDRESS = 'http://localhost:4444/wd/hub' | |
EXIT = False | |
def send(msg): | |
url = "https://api.pushover.net/1/messages.json" | |
data = { | |
"token": PUSH_TOKEN, | |
"user": PUSH_USER, | |
"message": msg | |
} | |
requests.post(url, data) | |
def get_drive(): | |
local_use = platform.system() == 'Darwin' | |
if local_use: | |
dr = webdriver.Chrome(executable_path = './chromedriver') | |
else: | |
dr= webdriver.Remote(command_executor=HUB_ADDRESS, desired_capabilities=DesiredCapabilities.CHROME) | |
return dr | |
driver = get_drive() | |
def login(): | |
# Bypass reCAPTCHA | |
driver.get("https://ais.usvisa-info.com/en-ec/niv") | |
time.sleep(1) | |
a = driver.find_element_by_xpath('//a[@class="down-arrow bounce"]') | |
a.click() | |
time.sleep(1) | |
print("start sign") | |
href = driver.find_element_by_xpath('//*[@id="header"]/nav/div[2]/div[1]/ul/li[3]/a') | |
href.click() | |
time.sleep(1) | |
Wait(driver, 60).until(EC.presence_of_element_located((By.NAME, "commit"))) | |
print("click bounce") | |
a = driver.find_element_by_xpath('//a[@class="down-arrow bounce"]') | |
a.click() | |
time.sleep(1) | |
do_login_action() | |
def do_login_action(): | |
print("input email") | |
user = driver.find_element_by_id('user_email') | |
user.send_keys(USERNAME) | |
time.sleep(random.randint(1, 3)) | |
print("input pwd") | |
pw = driver.find_element_by_id('user_password') | |
pw.send_keys(PASSWORD) | |
time.sleep(random.randint(1, 3)) | |
print("click privacy") | |
box = driver.find_element_by_class_name('icheckbox') | |
box .click() | |
time.sleep(random.randint(1, 3)) | |
print("commit") | |
btn = driver.find_element_by_name('commit') | |
btn.click() | |
time.sleep(random.randint(1, 3)) | |
Wait(driver, 60).until(EC.presence_of_element_located((By.XPATH, "//a[contains(text(),'Continue')]"))) | |
print("Login successfully! ") | |
def get_date(): | |
driver.get(DATE_URL) | |
if not is_logined(): | |
login() | |
return get_date() | |
else: | |
content = driver.find_element_by_tag_name('pre').text | |
date = json.loads(content) | |
return date | |
def get_time(date): | |
time_url = TIME_URL % date | |
driver.get(time_url) | |
content = driver.find_element_by_tag_name('pre').text | |
data = json.loads(content) | |
time = data.get("available_times")[-1] | |
print("Get time successfully!") | |
return time | |
def reschedule(date): | |
global EXIT | |
print("Start Reschedule") | |
time = get_time(date) | |
driver.get(APPOINTMENT_URL) | |
data = { | |
"utf8": driver.find_element_by_name('utf8').get_attribute('value'), | |
"authenticity_token": driver.find_element_by_name('authenticity_token').get_attribute('value'), | |
"confirmed_limit_message": driver.find_element_by_name('confirmed_limit_message').get_attribute('value'), | |
"use_consulate_appointment_capacity": driver.find_element_by_name('use_consulate_appointment_capacity').get_attribute('value'), | |
"appointments[consulate_appointment][facility_id]": "108", | |
"appointments[consulate_appointment][date]": date, | |
"appointments[consulate_appointment][time]": time, | |
} | |
headers = { | |
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36", | |
"Referer": APPOINTMENT_URL, | |
"Cookie": "_yatri_session=" + driver.get_cookie("_yatri_session")["value"] | |
} | |
r = requests.post(APPOINTMENT_URL, headers=headers, data=data) | |
if(r.text.find('Successfully Scheduled') != -1): | |
print("Successfully Rescheduled") | |
send("Successfully Rescheduled") | |
EXIT = True | |
else: | |
print("ReScheduled Fail") | |
send("ReScheduled Fail") | |
def is_logined(): | |
content = driver.page_source | |
if(content.find("error") != -1): | |
return False | |
return True | |
def print_date(dates): | |
for d in dates: | |
print("%s \t business_day: %s" %(d.get('date'), d.get('business_day'))) | |
print() | |
last_seen = None | |
def get_available_date(dates): | |
global last_seen | |
def is_earlier(date): | |
return datetime.strptime(MY_SCHEDULE_DATE, "%Y-%m-%d") > datetime.strptime(date, "%Y-%m-%d") | |
for d in dates: | |
date = d.get('date') | |
if is_earlier(date) and date != last_seen: | |
_, month, day = date.split('-') | |
if(MY_CONDITION(month, day)): | |
last_seen = date | |
return date | |
def push_notification(dates): | |
msg = "date: " | |
for d in dates: | |
msg = msg + d.get('date') + '; ' | |
send(msg) | |
if __name__ == "__main__": | |
login() | |
retry_count = 0 | |
while 1: | |
if retry_count > 6: | |
break | |
try: | |
print(datetime.today()) | |
print("------------------") | |
dates = get_date()[:5] | |
print_date(dates) | |
date = get_available_date(dates) | |
if date: | |
reschedule(date) | |
push_notification(dates) | |
if(EXIT): | |
break | |
time.sleep(SLEEP_TIME) | |
except: | |
retry_count += 1 | |
time.sleep(60*5) | |
if(not EXIT): | |
send("HELP! Crashed.") |
Hi @yaojialyu , can you tell me what is number 108 for in the DATE_URL and TIME_URL please?
Hi guys, I see that the APIs does not work if we call them from the codebase. Have the US Gov made changes in the server to not accept APIs?
Lo único malo es que el servidor lo bloquea a uno por entrar mucho :( Yo Hice un boot también, busco la manera acceder a api importando request, logro solo iniciar sesión, de ahí no he pasado pasar. Alguna forma de guardar hacer request.Session() y que no se pierda el registro cuando le hago peticiones get a la página de appoiment?
Hablame y lo checamos, yo busco lo mismo
Lo único malo es que el servidor lo bloquea a uno por entrar mucho :( Yo Hice un boot también, busco la manera acceder a api importando request, logro solo iniciar sesión, de ahí no he pasado pasar. Alguna forma de guardar hacer request.Session() y que no se pierda el registro cuando le hago peticiones get a la página de appoiment?
Hablame y lo checamos, yo busco lo mismo
Ya lo solucioné hace más de un año. Pero si lo que quieres es adelantar las citas, hasta hace mes y medio se podía, la Embajada ha cambiado todo.
Hey
Is there a way to contact you by email or anything? I await your response as soon as possible.
@yaojialyu
I want to work with you on a project similar to visa appointments , i want your email
Lo único malo es que el servidor lo bloquea a uno por entrar mucho :(
Yo Hice un boot también, busco la manera acceder a api importando request, logro solo iniciar sesión, de ahí no he pasado pasar. Alguna forma de guardar hacer request.Session() y que no se pierda el registro cuando le hago peticiones get a la página de appoiment?