בניתי אוטומציה שנכנסת כל עשר דקות לאתר זימון התורים של רופא מומחה, בודקת אם התפנה תור, ואם כן — שולחת לי מייל מיידי עם צילום מסך, ובמקביל מנסה לקבוע אותו לבד. ארבע ספריות npm, שרת קטן בענן, לא המחשב שלי. הדבר שלמדתי ממנה הוא שהחלק ה"חכם" בכלל לא היה החכם: ההתראה היא המוצר, וההזמנה האוטומטית היא בונוס שעוד לא הוכח.
הרקע פשוט. אין תורים אצל הרופא שרציתי. אבל תורים כן מתפנים, כל הזמן, כי אנשים מבטלים. הבעיה היא לא זמינות — היא שאף אדם שפוי לא ייכנס לאתר 144 פעם ביום כדי לבדוק.
מה זה עושה בפועל
הבוט הוא סקריפט Playwright שמריץ Chromium עם פרופיל קבוע, locale של he-IL ושעון ישראל, ומשחזר בדיוק את הצעדים שהייתי עושה בעצמי:
- פותח את המיני-סייט של הרופא ב-rofim.org.il וסוגר את הבאנר.
- לוחץ "קביעת תור" ובוחר את המבטח — כללית מושלם.
- ממשיך לזימון, ואז נוחת בתוך iframe שמוגש מדומיין אחר, shidurit.com — שם רץ מסך התורים עצמו.
- מקליד תעודת זהות בשדה ולוחץ שליחה. אין SMS ואין OTP — מספר תעודת הזהות הוא כל מה שהשדה הזה מבקש. יש גם שכבת זיהוי נוספת מצד האתר, ולזה עוד נגיע.
- קורא את מסך הזמינות.
הסיווג של המסך הזה הוא הלב של כל הדבר, והוא שלוש שורות:
- המסך נטען ויש בו "אין תורים זמינים" → אין תור. נספר בשקט, בלי מייל.
- המסך נטען ואין בו את המשפט הזה → יש תור. מייל מיידי.
- המסך בכלל לא נטען → שגיאה, לא "אין תור".
השורה השלישית היא ההבדל בין אוטומציה שאפשר לסמוך עליה לבין אוטומציה שמשקרת לך בשקט. אתר שהשתנה, סשן שפג, אלמנט שזז — כל אלה נראים בדיוק כמו "אין תורים" אם לא טורחים לוודא שהגעת למקום הנכון. אז לפני שהקוד מרשה לעצמו להסיק משהו, הוא מחפש עוגנים חיוביים בטקסט של המסך: "תור אצל", "התורים העתידיים", "שינוי מטופל". אין עוגן, אין מסקנה.
כל הרצה שומרת לתיקייה משלה צילום מסך ולוג. זה נשמע כמו ניקיון מיותר לסקריפט של ערב אחד, עד הפעם הראשונה שאתה שואל את עצמך למה לא קיבלת מייל.
בצד יש עוד סקריפט קטן שהוא כלי פיתוח בלבד: הוא מריץ את אותו מסלול בדיוק, אבל עם דפדפן גלוי, ובכל שלב מדפיס את כל האלמנטים הלחיצים שהוא רואה — תגית, id, class, טקסט — ושומר את ה-HTML של המסך האחרון. ככה מצאתי את הסלקטורים מלכתחילה, וככה אמצא אותם שוב ביום שהאתר יזוז. באוטומציה שרוכבת על ממשק של מישהו אחר, הכלי שעוזר לגלות מחדש את הממשק שווה בדיוק כמו הקוד שמריץ אותו.
התבנית: תשאל אתר גרוע עד שמשהו משתנה
הפרויקט הזה לא מעניין בפני עצמו. מה שמעניין הוא שהוא מקרה פרטי של תבנית שחוזרת בעשרות בעיות יומיום:
- יש משאב נדיר שמתפנה בזמנים אקראיים.
- הדרך היחידה לדעת שהתפנה היא להיכנס ולהסתכל.
- מי שנכנס ראשון מקבל אותו.
תור לרופא, תור בטסט, מקום בחוג, ביטול בבית ספר לנהיגה, מלאי שחוזר לחנות, תור בקונסוליה. אותה צורה בדיוק, מוסדות שונים. זו תבנית גרועה במיוחד לבן אדם — היא דורשת דבקות במשימה בקצב שאין לאף אחד — ובול מתאימה לאוטומציה קטנה ומקומית.
שימו לב מה אין פה. אין מודל, אין החלטה מורכבת, אין אינטגרציה מול API. יש דפדפן, לולאה, ותנאי עצירה. ה-AI לא נמצא בזמן ריצה — הוא נמצא בכתיבה: עם agent שכותב ומריץ קוד, המרחק בין "זה מעצבן אותי" לבין "זה רץ בענן" הוא ערב אחד. זה בדיוק סוג הדברים שאני מנסה ללמד אנשים לבנות לעצמם, כי אף אחד לא היה מגדיר את זה מראש כפרויקט.
מה שכן דורש מחשבה זה לא הלולאה. זה הקצוות.
ההתראה היא המוצר. ההזמנה היא בונוס.
עכשיו ההודאה: כשבניתי את זה לא היו תורים. בכלל. וזה אומר שמעולם לא ראיתי בעיניים את המסך שבו בוחרים שעה ומאשרים.
אז הקוד לא מעמיד פנים שהוא מכיר אותו. הוא עושה שני דברים נפרדים לגמרי:
- תמיד שולח מייל ברגע שהוא מזהה תור, עם צילום מסך ועם הטקסט של המסך. זה הערוץ שאני סומך עליו, כי הוא לא תלוי בשום סלקטור.
- מנסה לקבוע: סורק את כל האלמנטים הלחיצים בפריים, מוצא כאלה שהטקסט שלהם נראה כמו שעה בפורמט
HH:MM, מסנן לפי חלון שעות אופציונלי (אצלי הוא פתוח לגמרי), לוחץ על הראשון ברשימה הממוינת, ומחפש כפתור אישור לפי רשימת מילים — "אישור", "קבע תור", "אני מאשר". בסוף הוא מוודא בטקסט של המסך שהתור באמת נקבע. גם המיון הזה הוא ניחוש: הוא ממיין מחרוזות ולא שעות, כלומר הוא יחזיק רק אם המסך מרנדר "09:30" ולא "9:30" — ואת המסך האמיתי עוד לא ראיתי.
ואם הוא לא מזהה כלום? הוא שומר את ה-HTML המלא של המסך ואת צילומי המסך, ומשאיר לי לקבוע ידנית. כלומר: כשל של ההזמנה האוטומטית לא הופך לכשל של המערכת, הוא רק מוריד אותה דרגה — מ"הכול קרה" ל"תיכנס עכשיו". וההרצה הראשונה שתפגוש תור אמיתי תשמור בדיוק את הראיה שצריכה כדי לסגור את הפער.
זה עדיין המצב נכון לכתיבת השורות האלה. מאז שזה עלה לאוויר לא נתפס תור, ולכן הסלקטורים של מסך ההזמנה עדיין לא סופיים, ובינתיים ההזמנה בפועל היא שלי. יש גם מתג MODE=watch שמכבה לגמרי את הניסיון לקבוע ומשאיר רק התראות.
וכאן נכנס פרט קטן שהוא בעצם עיקר: אם ההתראה היא המוצר, אסור שהפעם הראשונה שהיא נשלחת תהיה גם הפעם הראשונה שבודקים אותה. אז יש משתנה סביבה שמכריח את הקוד להתייחס למסך כאילו נמצא בו תור, ושולח את המייל המלא עם הכותרת [TEST]. ככה ידעתי שהערוץ עובד בלי לחכות לאירוע שאולי יקרה בעוד חודשיים.
מה שחשוב לא לעשות
רוב העבודה באוטומציה כזאת היא דווקא בהגבלות. הכלל שלי: הבוט עושה בדיוק מה שהייתי עושה ידנית, רק בקצב סביר. הוא לא נלחם במוסד.
- קצב. בדיקה אחת כל עשר דקות. מספיק מהר כדי לתפוס ביטול, לא משהו שדומה לתקיפה.
- בקשה אחת בכל רגע. אם בדיקה קודמת עוד רצה, הטיק הבא פשוט מדלג. אין הצטברות.
- שתיקה כשאין חדשות. "אין תורים" רק נספר. מייל יש רק כשקרה משהו, ועוד סיכום יומי אחד ב-21:00.
- התראה אחת על תקלה. אחרי שש שגיאות רצופות — בערך שעה בקצב הזה — יוצא מייל אחד שאומר שהאוטומציה כנראה שבורה. אחד, לא שישה. הוא ננעל עד שהמערכת מתאוששת.
- נעילה אחרי הצלחה. ברגע שנקבע תור, הבוט מפסיק לגמרי. צריך למחוק את קובץ המצב כדי לדרוך אותו מחדש.
ועוד כלל שהוא לא בקוד אלא בהתנהגות: אם תפסת תור מוקדם יותר, תבטל את המאוחר באותו יום. כל הרעיון עובד כי אנשים מבטלים. אוטומציה שתופסת ולא משחררת שוברת בדיוק את המנגנון שהיא מנצלת.
איפה זה רץ
בהתחלה זה רץ אצלי על המק כ-launchd agent. זה עבד, אבל מחשב נייד נסגר ונוסע, והתפנות של תור לא מחכה. אז זה עבר לשרת ARM זעיר ב-AWS בריג'ן של תל אביב, כשירות systemd שעולה מחדש לבד. בחרתי בריג'ן הישראלי כי עם כתובת IP ישראלית ווידאתי שעוברים את שלב הזיהוי מול האתר. מה קורה מחוץ לישראל — לא בדקתי.
עלות מוערכת: בערך תשעה דולר בחודש. כל בדיקה מרימה דפדפן חדש וסוגרת אותו בסוף, כך שבין הבדיקות התהליך כמעט ריק וגם מכונה קטנטנה מספיקה.
מה לוקחים מזה
הרבה ממה שנקרא "אוטומציה" בארגונים הוא בדיוק זה: מישהו נכנס למסך כל כמה זמן כדי לבדוק אם משהו השתנה, ואז עושה פעולה קטנה. סטטוס משלוח, מכרז שנפתח, קובץ שהגיע לתיקייה, שדה שהתעדכן ב-CRM. זה לא מרגיש כמו פרויקט טכנולוגי כי זה לא — זו לולאה ותנאי עצירה.
מה שכן דורש שיקול דעת הוא ההפרדה שבניתי כאן בלי לתכנן אותה מראש: הפרד את לדעת מלפעול. החלק שיודע חייב להיות עמיד, מפורש ובטוח בעצמו רק כשיש לו ראיה. החלק שפועל יכול להיות שברירי, כל עוד הוא נכשל בקול והופך את עצמו לבעיה קטנה יותר במקום להיעלם.
ככה נראה התהליך שאני עושה עם ארגונים — קודם מחברים את הכלים, ואז מלמדים אנשים לבנות לעצמם את הדברים הקטנים האלה.