def listuj_linie(url): """ Funkcja wchodzi na podanego URL'a (w przypadku strony MPK, musi nast¹piæ przekierowanie, bo mamy index.jsp, a nie .html) i pobiera listê linii. TODO: rozró¿niaæ autobusy dzienne/nocne i tramwaje? Na tej podstronie jest taka mo¿liwoœæ. """ tree = html.parse(url+'/index.html') przekierowanie = tree.xpath('//meta [@http-equiv="refresh"]') if przekierowanie: #Wybierz pierwszy element z tej tablicy i weŸ tekst na #prawo od URL w jego 'content'. nowy_url = przekierowanie[0].attrib['content'].split( 'URL=')[-1] tree = html.parse(nowy_url) linie_tree = wybierz_ramke(tree,'rozklad',url) linie_td = linie_tree.xpath('//div [contains(@id,bx1)]//td \ [@class="nagl" and not(contains( \ .,"Aktualny"))]') ret = [] makedir_quiet('przetworzone') f = open('przetworzone/lista_linii.txt','w') for linia in linie_td: link = linia.xpath('a')[0] #wytnij "Linia: " z linka i uznaj to za nazwê linii nazwa_linii = link.text_content().lstrip("Linia: ") url_linii = url+link.attrib['href'] ret += [Linia(nazwa_linii,url_linii,url)] print(nazwa_linii,file=f) return ret
def pobierz_przystanki(self): """ Jeœli ju¿ mamy przystanki, zwróæ je. W przeciwnym razie wejdŸ na linka z obiektu, przeskocz ramki i dla ka¿dego z kierunków, przetwórz go. """ if not self.przystanki: tree = html.parse(self.url) tree = wybierz_ramke(tree,'rozklad',self.base_url) tree = wybierz_ramke(tree,'D',self.base_url) kat_linia = 'przetworzone/lista_przystankow/%s' % \ self.nazwa kierunki = tree.xpath('//td [@class="przyst"]') makedir_quiet(kat_linia) plik_ilosc_kier = open(kat_linia+'/il_kier.csv','w') print(len(kierunki),file=plik_ilosc_kier) plik_ilosc_kier.close() for i in range(len(kierunki)): self.przetworz_kierunek(kierunki[i],i) return self.przystanki
def przetworz_kolumne_rozkladu(self,godziny,minuty,i): """ Przetwarza pojedyncz¹ kolumnê rozk³adu - t¹ 'W dni robocze oprócz sobót', 'W soboty', 'W niedziela i œwiêta', 'Dnia x' itp. """ #Z za³o¿enia, nazwê katalogu mamy ustawion¹ przez klasê Linia. #Tworzymy go i otwieramy rozklad.csv dla danego podkatalogu i. nowy_katalog = "%s/%d" % (self.nazwa_katalogu, i) makedir_quiet(nowy_katalog) plik = open("%s/rozklad.csv" % nowy_katalog, 'w') #Wybieramy tr'ki z godzinami i minutami. Ma byæ ich tyle samo. tr_godziny = godziny.xpath('.//tr') tr_minuty = minuty.xpath('.//tr') assert(len(tr_godziny)==len(tr_minuty)) #Przechodzimy przez ka¿d¹ godzinê. for i in range(len(tr_godziny)): godzina = tr_godziny[i].text_content() godzina = int(godzina) wiersz_minut = tr_minuty[i] #Przechodzimy przez ka¿d¹ minutê. for td_minuta in wiersz_minut.xpath('.//td'): minuta = td_minuta.text_content() #TODO: poprawne przetwarzanie liter na koñcu. #Gdybym wiedzia³, jak ten kod siê rozroœnie, #rozwi¹za³bym to inaczej... for litera in ('x','A','B','C','N','D', 'd','a','s','T','R','z','P', 'f','n','J','y'): #Obetnij literkê na koñcu. minuta = minuta.rstrip(litera) if minuta=='-': #Siê znaczy - w tej kolumnie pod t¹ #godzin¹ nic nie ma. continue minuta = int(minuta) assert(godzina<24 and minuta<60) czas = '%d:%02d' % (godzina,minuta) print(czas,file=plik)
def przetworz_rozklad(url,base_url,stary_base_url,nazwa_linii,i): """ Pobieramy rozk³ad i przetwarzamy go. Do odczytania ramek potrzebne by³o czary_mary z base_url i stary_base_url. Wynika to ze sposobu, w jaki pliki z rozk³adami s¹ zapisane w pliku .zip na stronie. Poza znakiem zapytaniem w treœci, trzeba by³o jeszcze jakoœ rozwi¹zaæ "../" w adresach. """ zwracany_rozklad = Rozklad() docelowy_url = popraw_file_url(base_url+url) tree = html.parse(docelowy_url) if url.find('ramka.html?l=')!=-1: #wersja z ZIPa #wybieramy l= oraz p= z URL'a i symulujemy dzia³anie #kodu JS w ZIPach - ³adujemy odpowiedni plik. par = re.findall('\?l=(.*?)&p=(.*?)&k',url)[0] nowy_url = "%s/%s/%s.htm" % ( stary_base_url,par[0],par[1]) try: #USUN¥Æ PO TESTACH tree = html.parse(nowy_url) except: print("t³umiê b³¹d pobierania: %s" % nowy_url) return #tree = html.fromstring( # nowy_html.decode('windows-1250')) else: #wersja ze strony tree = wybierz_ramke(tree,'T',base_url) #Wybieramy dwie g³ówne tabele. glowne_tabele = tree.xpath('//td [@valign="TOP"]') assert(len(glowne_tabele)==2) #Nastêpnie, wyci¹gamy tabelê z czasami oraz rozk³adem. tabela_z_czasami = glowne_tabele[0] tabela_z_rozkladem = glowne_tabele[1].xpath('./table')[0] assert(len(tabela_z_rozkladem.xpath('./tr'))==4) #ID przystanku jest w takim TD, który nie ma ustawionej klasy #a jednoczeœnie ma colspan=2 i align=center. id_przystanku_td = tree.xpath('//td[not(@class="naglczas") \ and @align="CENTER" and @colspan="2"]') assert(len(id_przystanku_td)==1) #TODO: Mo¿e to jest lepsze miejsce do wyci¹gania nazw #przystanków? id_przystanku_tekst = id_przystanku_td[0].text_content() #Wzorzec - coœtam, coœtam w nawiasie, koniec. Interesuje nas #to drugie coœtam. id_przystanku = re.findall('(.*)\((.*?)\)$', id_przystanku_tekst)[0] #Ustawiamy to zwracanemu obiektowi. zwracany_rozklad.id_przystanku = id_przystanku[1] #utwórz na wszelki wypadek katalog na listy przystanków, #a nastêpnie otwórz plik_lista, gdzie dopiszemy i-ty kierunek nazwa_katalogu = 'przetworzone/lista_przystankow/'+nazwa_linii makedir_quiet(nazwa_katalogu) plik_lista = open("%s/%d.csv" % (nazwa_katalogu,i),'a') print("%s" % id_przystanku[1], file=plik_lista) plik_lista.close() #Tworzymy katalog dla tego konkretnego rozk³adu. nazwa_katalogu = 'przetworzone/rozklady/%s/%s' % (nazwa_linii, id_przystanku[1]) makedir_quiet(nazwa_katalogu) #To te¿ ustawiamy zwracanemu obiektowi. zwracany_rozklad.nazwa_katalogu = nazwa_katalogu #Wybieramy tr'ki z tabeli z rozk³adem. Rozk³ad to drugi tr, #nag³ówek ('W niedziele/dni robocze' itp) jest w pierwszym. wiersze_tabeli_z_rozkladem = tabela_z_rozkladem.xpath('./tr') rozklad = wiersze_tabeli_z_rozkladem[2] naglowki = wiersze_tabeli_z_rozkladem[0] #Otwieramy plik na nag³ówki. plik_naglowki = open('%s/naglowki.csv' % nazwa_katalogu ,'w') #Wyci¹gamy z rozk³adu kolumny i iterujemy od 0 do po³owy ich #liczby. kolumny_rozkladu = rozklad.xpath('./td') for i in range(int(len(kolumny_rozkladu)/2)): #Zczytujemy nazwê nag³ówka i zapisujemy j¹. nazwa_naglowka = naglowki[i].text_content() print("%s,%s" % (i,nazwa_naglowka),file=plik_naglowki) #Przetwarzamy parê kolumn rozk³adu - godziny i minuty. zwracany_rozklad.przetworz_kolumne_rozkladu( kolumny_rozkladu[i*2], kolumny_rozkladu[i*2+1],i) return zwracany_rozklad
def obsluz_przesiadki(self,link): """ Wstêpny kod obs³ugi przesiadek. Klika w link "przesiadki" dla danego przystanku i listuje, jakie linie s¹ na danym przystanku. UWAGA, du¿e. """ url = link.attrib['href'] #wyci¹gamy treœæ przed ostatnim ukoœnikiem jako #base_url_rozkladu. base_url_rozkladu = re.findall('^(.*)/(.*)$', self.url)[0][0]+'/' #B³êdy tego typu maj¹ miejsce w ZIPach MPK. PóŸniej im to #pewnie zg³oszê. docelowy_url = base_url_rozkladu+url try: tree = html.parse(docelowy_url) except: print("t³umiê b³¹d pobierania: %s" % docelowy_url) return #Dane przystanku s¹ w jakimœ divie albo foncie. Ma byæ jeden. dane_przystanku_el = tree.xpath( '//*[self::font or self::div]') assert(len(dane_przystanku_el)==1) dane_przystanku_tekst=dane_przystanku_el[0].text_content() #Dzielimy to wed³ug wzorca - coœtam, coœtam w nawiasie, koniec. dane_przystanku = re.findall('(.*)\((.*?)\)$', dane_przystanku_tekst)[0] nazwa_przystanku = dane_przystanku[0] #pierwsze coœtam #Poni¿sze trzy linijki daj¹ pewne wyobra¿enie o tym jakiej #jakoœci s¹ dane z ZIPa. nazwa_przystanku = nazwa_przystanku.lstrip('null') nazwa_przystanku = nazwa_przystanku.lstrip() nazwa_przystanku = nazwa_przystanku.lstrip('- ') nazwa_przystanku = nazwa_przystanku.rstrip() id_przystanku = dane_przystanku[1] #drugie coœtam nazwa_pliku_przesiadki = 'przetworzone/przesiadki/%s.txt' % \ id_przystanku """ Je¿eli istnieje ju¿ plik z przesiadkami, ustawiamy plik na None, ¿eby go nie dopisywaæ do bazy przesiadek. Przy okazji, jeœli nie ma go w przesiadkach, dopiszmy go te¿ do nazwy_przystankow.txt. """ if not os.path.exists(nazwa_pliku_przesiadki): makedir_quiet('przetworzone/przesiadki') plik = open(nazwa_pliku_przesiadki,'a') plik_przystanki = open('przetworzone/'+\ 'nazwy_przystankow.txt','a') print("%s,%s" % (id_przystanku,nazwa_przystanku), file=plik_przystanki) plik_przystanki.close() else: plik = None #przechodzimy przez ka¿dy tag <p> for p in tree.xpath('//p'): #dotyczy tylko strony WWW if p.text_content().endswith('na mapie'): continue #je¿eli potem jest ul, to najprawdopodobniej jest to #lista przesiadek. nast_el = p.getnext() if(nast_el.tag=='ul'): for el in nast_el.xpath('li'): #uwaga na link! znowu bêdzie problem #z ramka.html w ZIPie link = el.xpath('a')[0] nazwa_linii = link.text_content() nazwa_linii = nazwa_linii.strip() kier_tekst = link.tail kier_tekst = kier_tekst.split('-->')[1] kier_tekst = kier_tekst.strip() if plik: print('%s,%s' % (nazwa_linii, kier_tekst), file=plik) break #chyba, ¿e potrzebujemy linie w pobli¿u?