ホームページ > 記事 > ウェブフロントエンド > UTD ハッカソンの概要_html/css_WEB-ITnose
これは、少し前に UTD ハッカソンに参加したときのまとめです。
TAMUのクラスメイトに誘われて一緒に行きました。 私は主にクローラー部分を担当しました。なので、ここでは主に私の仕事について話します。その他の理解できない部分については詳しく説明しないので、バグレモンの話はやめておきます。
このプロジェクトの出発点は、運転免許試験を予約するための 12306 チケット取得アシスタントに似たツールを開発したいということです。主な理由は、私のクラスメートからの要望でした。アメリカ人は、電車の切符を買うのと同じように、運転免許試験の予約をする必要があることが分かりました。しかし、ここでの落とし穴は何でしょうか? TAMU がある学生街は非常に混雑しているため、春節の旅行列車のチケットと同様に予約をし続ける必要があります。
同級生によると、中国人がこのソフトを開発し、外部に販売したそうです。もちろん、この動作については後で説明します。まず、私たちのような自分でやりたい人がお金を出してこれを購入することを期待するのは非現実的です。そこで今回は私のクラスメートが彼の後輩 2 人とチームを組み、一緒にこのプロジェクトを開発しました。
私たちのプロジェクトはここにあり、すべてオープンソースです。もちろん、時間が限られているため、コードの一部は非常に大まかであり、修正は歓迎されます。
HackUTD: 利用可能な運転試験の予約を見つける
まず第一に、関数を自動化したい場合は、この関数を手動で実装できなければなりません。高度な AI 設計がなければ、コンピューターが独自に特定の機能を自動的に実装することは困難です。
まず、コンピューターによる予約プロセスは、下の図に示すように、テキサス州公安局を開き、サービス (通常は車の予約) を選択します。もちろん、TAMU がある学生街である 2571 North Earl Rudder Freeway Bryan, TX 77803 という都市をすでに選択しています。
すると、この表の灰色のスケジュールが満席、白いスケジュールが予約可能になります。当日予約は不可、90日を超える予約はできないので注意が必要です。
この Web ページは、クリックすると生成されると同時に、テーブルの月と日の列に左右の矢印があることに注意してください。これら 2 つの矢印を開くと、それぞれ 2 つの Javascript スクリプトに対応し、一部の Web ページを動的に更新する機能が実現されます。
静的 HTML ページの場合、Beautiful Soup を使用してページを解析し、必要なページ コンテンツを取得できますが、Ajax と Javascript をどのように扱うか?
一般的に言えば、2 つあります。アイデア:
私は 2 番目の方法を選択し、Selenium の Webdriver 関数を使用して解析を実装しました。このようにして、ブラウザーのクリックやその他の動作をシミュレートすることで、簡単に対話できます。
次に、必要な静的 HTML を取得した後、対応する解析と処理を実行するだけです。主に、必要な情報は日付と登録可能かどうかだけなので、この日付でマークされたデータを分析するだけで済みます。DPS Web ページはすべての日付が 4 つのカテゴリに分類されており、カレンダーは閉じられています。 is は現在の日を指し、calendar-notavailable は 90 日以上前の日付、calendar-fullday は 90 日以内であるが完全に登録されている日付、そして、calendar-available は、名前が示すとおりです。 , は登録可能な日付です。したがって、情報をクロールし、クラスを通じてこれらの属性を直接取得するのは非常に簡単です。最終結果は、他のプログラムで使用できるようにデータベースに保存されます。
上の図は全体的な設計フレームワークです。主要な部分は、フロントエンドが最初に Ruby on Rails に基づいているということです。 UI の効果は次のとおりです。
バックエンドは、予約情報 Web サイトを 10 分ごとにスキャンする更新スクリプトを実装します。その後、相違が検出され、その日付が登録ユーザーの指定日である場合、電子メール プログラムが呼び出され、ユーザーに予約情報を記載した電子メールが送信され、できるだけ早くオンラインで予約するようユーザーに通知します。
このタスクは実際には比較的単純ですが、それでも接続できるのは非常に良いことです。もちろん、一般のユーザーにとっては、それほど多くの詳細を公開する必要はありません。実際、Web サイトを作成するだけで十分であり、ユーザーが使用できる主な部分はフロント部分です。バックエンドはすべてオンラインに配置する必要があります。
もちろん、便利であればiOSやAndriodクライアントを実装した方が良いでしょう。
これは後で解決されます。
#!/usr/bin/env python# -*- coding: utf-8 -*-"""Created on Sun Mar 27 06:42:50 2016@author: iphyeroutput :return value1 means sth changed0 nothing changed"""#import needed packagefrom selenium import webdriver # web actionfrom pyvirtualdisplay import Displayfrom datetime import dateimport BeautifulSoup as bsimport sqlite3import pickle# function setupdef htmltableGetinfomation(websource,data_page): """ get information from html source input : html source code output : dict of data and availibility """ month2num = { 'January' : 1, 'February': 2,'March' : 3,'April': 4,'May': 5,'June': 6,'July' : 7,'August': 8, 'September': 9, 'October': 10, 'November' : 11, 'December': 12} soup = bs.BeautifulSoup(websource) table = soup.find(lambda tag: tag.name=='table' and tag.has_key('id') and tag['id']=="calendar") temp = table.findAll('span') Mon, Year = temp[0].string.split() # insert starting day calendar-closed Mon = month2num.get(Mon) Mon = int(Mon) Year = int(Year) days_closed = table.findAll(lambda tag: tag.name=='td' and tag.has_key('class') and tag['class'] == 'calendar-closed') for i in days_closed: Day = int(i.text) date_temp = date(Year,Mon,Day).strftime("%m/%d/%Y") data_page[date_temp] = 0 # insert following day calendar-fullday days_full = table.findAll(lambda tag: tag.name=='td' and tag.has_key('class') and tag['class'] == 'calendar-fullday') for i in days_full: Day = int(i.text) date_temp = date(Year,Mon,Day).strftime("%m/%d/%Y") data_page[date_temp] = 0 # insert following day calendar-available days_available = table.findAll(lambda tag: tag.name=='td' and tag.has_key('class') and tag['class'] == 'calendar-available') for i in days_available: Day = int(i.text) date_temp = date(Year,Mon,Day).strftime("%m/%d/%Y") data_page[date_temp] = 1 #print "===========================================" #print data_page return data_pagedef creat_sqlite(Allowed_Days_Dict): """ creat sqlite of 90 allowed time with their availability input : Allowed_Days_Dict = {date : availability} """ #connecting database and creating table availability conn = sqlite3.connect("development.sqlite3") cursor = conn.cursor() cursor.execute("""DROP TABLE IF EXISTS availability""") cursor.execute("""CREATE TABLE IF NOT EXISTS availability (date text,av int) """) dictlist = [] for key, value in Allowed_Days_Dict.iteritems(): temp = [key,value] dictlist.append(temp) cursor.executemany("INSERT INTO availability VALUES (?,?)" ,dictlist) conn.commit() cursor.close() conn.close()def sqlreading(): pkl_file = open('myfile.pkl', 'rb') Allowed_Days_Dict_old = pickle.load(pkl_file) pkl_file.close() return Allowed_Days_Dict_olddef dictDiff(dictA,dictB): for key,val in dictA.iteritems(): if ( val != dictB[key] ): return 1def renewSQL(changed,Allowed_Days_Dict): if ( changed ): creat_sqlite(Allowed_Days_Dict) output = open('myfile.pkl', 'wb') pickle.dump(Allowed_Days_Dict, output) output.close()if __name__ == "__main__": """ method description : 1.get four month available and unavailable days and then return as a dict 2.dict to sqlite """ #Assign URL for search #Appointment Locator # Location Address # 2571 North Earl Rudder Freeway # Bryan, TX 77803 URL = 'https://booknow.securedata-trans.com/1qed83ds/' #four_months for result record Allowed_Days_Dict = dict() # get webpage information display = Display(visible=0, size=(800, 600)) display.start()# now Firefox will run in a virtual display. # you will not see the browser. browser = webdriver.Firefox() browser.implicitly_wait(5) browser.get('https://booknow.securedata-trans.com/1qed83ds/') browser.find_element_by_xpath("//select[@name='service_id']/option[text()='Driving Test - Regular Car / Pick-up Truck']").click() source = browser.page_source Allowed_Days_Dict = htmltableGetinfomation(source,Allowed_Days_Dict) #get another 3 pages information for i in range(1,4): browser.execute_script("javascript:dosubmit1('no', 'yes', 'log_in')") source = browser.page_source Allowed_Days_Dict = htmltableGetinfomation(source,Allowed_Days_Dict) #print "===========================================" #print Allowed_Days_Dict browser.close() #reading in the old date dict Allowed_Days_Dict_old = sqlreading() changed = 0 changed = dictDiff( Allowed_Days_Dict_old, Allowed_Days_Dict) renewSQL(changed,Allowed_Days_Dict) print "================update_10min Done===========================" exit(changed)