Помогите разобраться - как извлечь информацию со страницы?

MarizzaMarizza

Столкнулась со следующей практической задачей: нужно заняться поиском авиабилетов, но поиск сильно осложнен тем, что я пока не знаю ни точных дат поездки, ни куда я еду. Вот такое классическое "найди то, не знаю что".
Перебирать на поисковиках типа skyscanner или momodo все даты - это я состарюсь раньше, чем закончу.
В связи с этим возникла идея автоматизировать процесс - не зря же я учила питон.
Думала взять тупо в лоб - сделать запрос и спарсить страничку. И тут-то меня ждал облом.
Возьмем, например, такой запрос:
http://awd.momondo.ru/flightsearch/?Search=true&TripType=4&SegNo=1&SO0=MOW&SD0=L&SDP0=15-01-2016&AD=1&TK=ECO&NA=false#Search=true&TripType=1&SegNo=1&SO0=MOW&SD0=L&SDP0=15-01-2016&AD=1&TK=ECO&DO=false&NA=true
Допустим, нас интересует только самый дешевый рейс (тот, который в красной шапке таблицы). Смотрим код этого элемента и видим:
 <li id="flight-tickets-sortbar-cheapest" class="option cheapest active" data-sort-by="price">
<div class="inner">
<i aria-hidden="true" data-icon="&#xe011;"></i>
<span class="title">Дешевый</span>
<span class="info"></span>
</div>
</li>

А вот что мы видим для класса info:
<div class="info">
<div class="class">{ticket.typeName}</div>
{formatted.fee}
<div class="rating" onmouseover="$mm.flightRenderer.displayRatingTooltip(this,
'rating-tooltip-{flightkey}', -6);" onmouseout="$mm.flightRenderer.hideRatingTooltip(this,
'rating-tooltip-{flightkey}');" data-tooltip="{ratingTooltip}"><span class="value">{rating}</span></div>
</div>

И тут мысль останавливается. Как извлечь отсюда значение нужной переменной (видимо это formatted.fee)?

Temach

Вот такое классическое "найди то, не знаю что".Перебирать на поисковиках типа skyscanner или momodo все даты - это я состарюсь раньше, чем закончу. В связи с этим возникла идея автоматизировать процесс - не зря же я учила питон.
как именно? какие данные ты хочешь получить и что они тебе дадут в плане выбора путешествия?
пс. питона в топку. юзай грисманки

uncle17

Бешеные аяксы...
Особо не разбирался, но, судя по тому, как у них там всё наворочено, лично я бы на их месте тебе даже адресов скриптов своих просто так не показал, чтоб знать хотя бы, куда эти аяксы ломятся :)))
Ну можно, конечно, проследить, кто и куда ломится, но там тоже наверняка стоит защита по кукам или сессиям
Так что грейсманки, да...

MarizzaMarizza

Вы простите блондинку, но предполагается, что грейсманки сможет мне выцепить значение этой переменной? Или что он будет делать поиск? Если поиск, то, боюсь, это не совсем то, потому что данные все равно надо куда-то выгружать, а в этом как раз и есть основная проблема - неясно, как это делать.
Я хотела бы следующее:
 - как минимум - пробежать по всем датам и всем интересующим меня направлениям и выгрузить минимальные цены в файлик, чтобы потом просто посмотреть файлик и понять, в каком месяце и куда стоит лететь.
 - как максимум - выгрузить не только самый дешевый, но по паре других удобных для меня рейсов (например, не больше одной пересадки и переседка не дольше 3-4 часов). Чтобы потом в спокойной обстановке это изучить.

uncle17

Тогда не уверен, что оно поможет. Но я с ним знаком только теоретически.
Ну вот чтоб в файлик - точно надо разбираться, куда оно какие запросы шлёт, что в этих запросах передаёт браузер, что от этих запросов ожидает бекенд.. А потом уже их же и отправлять скриптом через тот же cURL, к примеру.

luna89

Самое удобное - берешь phantom.js (это google chrome с обрезанным GUI, собранный в один бинарник и позволяющий писать скрипты типа "открыть такой-то url, выдернуть данные, выплюнуть их в stdout". Пишешь скрипт, который открывает нужный тебе сайт, дожидается окончания аякс запросов, и выдирает все данные через DOM API.
Питон не поможет, правда - нужно минимальное знание js.

uncle17

А вообще не надо блондиностью прикрываться - задачка-то совсем не тривиальная :)

luna89

Ну вот чтоб в файлик - точно надо разбираться, куда оно какие запросы шлёт, что в этих запросах передаёт браузер, что от этих запросов ожидает бекенд.. А потом уже их же и отправлять скриптом через тот же cURL, к примеру.
Вот это самое правильное - открой сайт в хроме, включи developer tools, посмотри какие запросы шлются. Скорее всего там есть нормальное rest api

yroslavasako

подразумевается, что тебя ждёт левел-ап: http://selenium-python.readthedocs.org/
этот сайт не отдаёт тебе данные. Он отдаёт приложение, написанное на javascript, которое уже впоследствии занимается отрисовкой и обменом. Ты не можешь его распарсить, ты должна его запустить. Для запуска веб приложений в искусственном окружении используется selenium. Он позволяет получить финальный вывод программы после её отработки.

MarizzaMarizza

Спасибо, посмотрю!
Какие запросы шлет - уже смотрела, их там туева хуча. Он же проходится по многим агентствам по продаже билетов и сайтам авиакомпаний.
Посмотрела js файлы, которые есть на momondo.ru и momondo.net - этой переменной там нет. Видимо, специально прячут от таких, как я.
Федя, я ж думала, там все просто! А оказалось непросто...

uncle17

Посмотрела js файлы, которые есть на momondo.ru и momondo.net - этой переменной там нет. Видимо, специально прячут от таких, как я.
Ну вот даже собсно строки "flightRenderer" не видать в открытом тексте.
Есть, правда, кусок кода

<script type="text/javascript">_MomondoTripType='';_MomondoFlightSearchUrl='/multicity/';_DefaultResultView=0;_DefaultOverview='';_FlightRedirectBehavior=3</script>

Вполне возможно, что как раз по этому "/multicity/' еще кусок JS и отдается. Ну или еще примерно в таких местах. В общем, интересно, но лично мне разбираться точно лень :)))

MarizzaMarizza

Перечитала твой пост раза три. Кажется, поняла, что надо делать, но не уверена. Пойду курить мануалы.
2 l0st: я знаю про этот функционал, но мне показалось, что он не особо точен. Самый интерес представляют вещи типа ошибок авиакомпаний (типа - добавь третий сегмент и получи три билета по цене в два раза ниже, чем за два). В идеале написать бы поисковик для таких штук. Тут скайсканнер не поможет - он не умеет искать составные маршруты.
Хотя для решения конкретно моей практической задачи твое предложение, пожалуй, самое быстро реализуемое. :)
Ну и когда я попыталась забрать данные с momondo скриптом, мне уже стало интересно, как это сделать.

uncle17

Скорее всего там есть нормальное rest api
Поверхностным поиском не выявлено.
Может, быстрее у них спросить? И если он есть, то и воспользоваться? :)

kill-still

Всё довольно просто. Сначала он идёт сюда (параметры поиска передаются через Referer):
http://awd.momondo.ru/api/3.0/FlightSearch
и получает в json идентификатор скролла (параметр SearchId):

{
"Segments" : [{
"Origin" : {
"Aliases" : null,
"ContinentCode" : null,
"ContinentGroup" : 0,
"CountryCode" : "RU",
"CountryName" : "Россия",
"DST" : null,
"DisplayName" : "Москва (MOW), Россия",
"Iata" : "MOW",
"IataLink" : false,
"Icao" : null,
"Latitude" : 55.7557869,
"Longitude" : 37.6176338,
"MainCityCode" : "MOW",
"MainCityDisplayName" : "Москва (MOW), Россия",
"MainCityName" : "Москва",
"Name" : "Москва",
"Priority" : 483,
"StateCode" : "",
"StateName" : "",
"TimeZone" : 0
},
"Destination" : {
"Aliases" : null,
"ContinentCode" : null,
"ContinentGroup" : 0,
"CountryCode" : "FI",
"CountryName" : "Финляндия",
"DST" : null,
"DisplayName" : "Хельсинки (L), Финляндия",
"Iata" : "L",
"IataLink" : false,
"Icao" : null,
"Latitude" : 60.31938,
"Longitude" : 24.9412041,
"MainCityCode" : "L",
"MainCityDisplayName" : "Хельсинки (L), Финляндия",
"MainCityName" : "Хельсинки",
"Name" : "Хельсинки-Вантаа",
"Priority" : 178,
"StateCode" : "",
"StateName" : "",
"TimeZone" : 0
},
"Departure" : "2016-01-15T00:00:00"
}
],
"SearchId" : "880a08fe-655e-45ec-8aad-801f160bf379",
"EngineId" : 8,
"AdultCount" : 1,
"ChildCount" : 0,
"InfantCount" : 0,
"ChildAges" : [],
"TicketClass" : "ECO",
"Culture" : "ru-RU"
}

После этого порциями по этому url:
http://awd.momondo.ru/api/3.0/FlightSearch/880a08fe-655e-45ec-8aad-801f160bf379/8/true
получает результаты поиска:

{
"SearchId" : "880a08fe-655e-45ec-8aad-801f160bf379",
"EngineId" : 8,
"Done" : false,
"Error" : false,
"ErrorMessage" : null,
"ResultNumber" : 1,
"Summary" : {
"BestOfferIndex" : 366,
"BestOfferSupplierIndex" : 17,
"CheapestOfferIndex" : 411,
"CheapestOfferSupplierIndex" : 19,
"FastestOfferIndex" : 366,
"FastestOfferSupplierIndex" : 17,
"Mauration" : 1730,
"MaxPrice" : 3835.73,
"MaxScore" : 2607.86,
"MinDuration" : 100,
"MinPrice" : 80.58,
"MinScore" : 129.9
},
"Airports" : [...],
"Airlines" : null,
"Fees" : [...],
"Flights" : [...],
"Legs" : [...],
"MixOffers" : null,
"Offers" : [{
"AdultPrice" : 0.0,
"AdultPriceEUR" : 0.0,
"AdultPriceExclTax" : 0.0,
"Currency" : "RUB",
"Deeplink" : "http://avia.tickets.ru/preloader?StartAirp1Code=MOW&EndAirp1Code=L&Date1=15-01-2016&adt=1&chd=0&inf=0&refid=72&class=E&r_hash=d3e60c91e3eaa5bdc0330ca9e3fb0482_PS576|PS151|:*43b9d43&act=book",
"FeeIndexes" : [16, 18, 24, 25, 26],
"FlightIndex" : 7,
"MobileDeepLink" : null,
"Score" : 302.79,
"TicketClassIndex" : 3,
"TotalIsCalculated" : false,
"TotalPrice" : 4983.00,
"TotalPriceEUR" : 80.58,
"TotalPriceExclTax" : 0.0
},
...
],
"TicketClasses" : [{
"Code" : "ECO",
"Name" : "economic_discounted"
}
]
}

Объединяет порции в один массив, сортирует по цене и отображает.

uncle17

http://awd.momondo.ru/api/3.0/FlightSearch
Раскопал :)))

MarizzaMarizza

Круууууто! Спасибо!
Блин, для меня пока что такое - за гранью не то что способностей, а даже понимания. В жизни не нашла бы.

kill-still

Пожалуйста.
Последнюю порцию можно идентифицировать по

"Done" : true,

MarizzaMarizza

Правильно ли я поняла:
1) я пишу запрос на http://awd.momondo.ru/api/3.0/FlightSearch , в качестве HTTP referer передаю ту строку, которая была в моем первом посте
2) скачиваю файл FlightSearch.json и вытаскиваю из него SearchId
3) подставляю его в http://awd.momondo.ru/api/3.0/FlightSearch/
4) отправляю запрос на получившийся url до тех пор, пока в ответ не получу файл с содержимым null
5) Ну дальше вроде все просто.
UPD: не файл с null, а Done = true

kill-still

2) скачиваю файл FlightSearch.json и вытаскиваю из него SearchId
Ты не скачиваешь файл, ты получаешь строку с текстом, в котором лежит JSON
4) отправляю запрос на получившийся url до тех пор, пока в ответ не получу ...
JSON c Done=true

MarizzaMarizza

Спасибо!

kill-still

Удаачи в танцах с бубном.

uncle17

4) отправляю запрос на получившийся url до тех пор, пока в ответ не получу JSON c Done=true
Если SearchID - это ID сессии (логичЬно), то "до тех пор" может быть ограничен временем сессии

kill-still

Если SearchID - это ID сессии (логичЬно), то "до тех пор" может быть ограничен временем сессии
Нет, Федя, SearchID - это ID курсора по результатам выдачи поискового запроса. Куки/сессии тут не при чем вообще.

uncle17

Например:
Ага, ознакомился. Хотя, в общем-то, по тому, для чего нужны - те же сессии :grin:
P.S. Не, я на них не дрочу, просто так получилось :grin:

Temach

Я хотела бы следующее: - как минимум - пробежать по всем датам и всем интересующим меня направлениям и выгрузить минимальные цены в файлик, чтобы потом просто посмотреть файлик и понять, в каком месяце и куда стоит лететь. - как максимум - выгрузить не только самый дешевый, но по паре других удобных для меня рейсов (например, не больше одной пересадки и переседка не дольше 3-4 часов). Чтобы потом в спокойной обстановке это изучить.
скайсканер или авиасейлс разве неумеют это из коробки?

ivanivan

Если что, то skyscanner имеет возможность поиска билетов без дат и конкретных городов.
Достаточно при выборе даты выбрать "Весь месяц", а в поле куда выбрать "Везде", дальше даст возможность выбрать страну и дату с самыми дешевыми билетами =)

MarizzaMarizza

Я опять застопрорилась.
Код:
 
 import requests

search_url = 'http://awd.momondo.ru/flightsearch/?' + \
'Search=true&TripType=1&SegNo=1&SO0=MOW&SD0=L&' + \
'SDP0=15-01-2016&AD=1&TK=ECO&DO=false&NA=false#Search=true' + \
'&TripType=1&SegNo=1&SO0=MOW&SD0=L&SDP0=15-01-2016&AD=1&' + \
'TK=ECO&DO=false&NA=false'

mom_url = 'http://awd.momondo.ru/api/3.0/FlightSearch'

search_headers = {'Referer':search_url}

search_result = requests.get(mom_url, headers = search_headers)

print (search_result.json()) # Для начала пытаюсь просто напечатать json

В ответ радостно получаю "Ready". И все.
Если добавляю "http.client.HTTPConnection.debuglevel = 1", вижу вот что:
 
send: b'GET /api/3.0/FlightSearch HTTP/1.1\r\nHost: awd.momondo.ru\r\nUser-Agent: python-requests/2.7.0 CPython/3.4.3 Windows/8\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nReferer: http://awd.momondo.ru/flightsearch/?Search=true&TripType... */*\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Via header: Connection header: Proxy-Connection header: Content-Length header: Expires header: Date header: Content-Type header: Server header: Cache-Control header: Pragma header: Set-Cookie header: Set-Cookie header: Set-Cookie header: X-AspNet-Version header: Set-Cookie

Мой Referer передался, но, видимо, сервер его не принял, так что ли? Потому что почему иначе он не передал json? Или, может, ему нужны еще какие-то заголовки? Может, он user-agent видит и злорадно меня посылает?

evgen5555

Не надо рефереров никаких
 
import urllib2
import json

search_request = {"AdultCount":1,
"ChildAges":[],
"TicketClass":"ECO",
"Segments":[{"Origin":"MOW","Destination":"L","Depart":"2016-01-15T17:00:00.000Z","Departure":"2016-01-15"}],
"Culture":"ru-RU",
"Mix":"None",
"Market":"",
"DirectOnly":False,
"IncludeNearby":True
}

req = urllib2.Request(
url = 'http://awd.momondo.ru/api/3.0/FlightSearch',
data = json.dumps(search_request),
headers = {'Content-Type': 'application/json'}
)



f = urllib2.urlopen(req)

search_object = json.loads(f.read())

search_id = search_object['SearchId']
engine_id = search_object['EngineId']

search_url = "http://awd.momondo.ru/api/3.0/FlightSearch/%s/%s/true" % (search_id, engine_id)
print "Opening", search_url
f = urllib2.urlopen(search_url)

print f.read()

kill-still

Ой, я не пролистал до тела запроса.

sutulin

Почему-бы не использовать API какого-нибудь сервиса?
http://business.skyscanner.net/portal/en-GB/Documentation/Fl...
http://support.travelpayouts.com/hc/ru/sections/200613133-%...

MarizzaMarizza

Тоже хорошая мысль. Но я уже начала писать по момондо, у него апи нет.
Возможно, как закончу - попробую и твой вариант.

uncle17

Но я уже начала писать по момондо, у него апи нет
В смысле?
А Кротишка тебе что озвучил?

bav46

Но я уже начала писать по момондо, у него апи нет.
а это что ?
search_url = "http://awd.momondo.ru/api/3.0/FlightSearch/%s/%s/true" % (search_id, engine_id)

MarizzaMarizza

Ну я предполагала, что апи поставляет разработчик, ну и вообще что это что-то официальное.

MarizzaMarizza

В общем, всем спасибо, особенно Асету и Кротишке. Асетов код пришлось переписать, т.к. я использую третий питон и другие библиотеки, но главное - это идея. В итоге все выгрузила. Теперь дело за малым - сделать перебор дат и мест прибытия и выбрать из этого нужную инфу, с этим сложностей нет.
Расскажите, как вы смотрели, какие запросы шлет сайт - через Developer tools в браузере?

digenet

Подскажите ещё пожалуйста, как можно авторизоваться используя логин и пароль , для конкретики/примера - на forumlocal, также используя питон.

356ft85

Подскажите ещё пожалуйста, как можно авторизоваться используя логин и пароль , для конкретики/примера - на forumlocal, также используя питон.
Общий метод такой:
Берёшь браузер например хром или оперу, или ФФ, и нажимаешь на Ctrl+Shift+I
появляется панель разработчика, в ней переключаешься на вкладку "сеть"
затем в переходишь на страничку где вводишь логин пароль , вводишь их и смотришь , что появляется в логах сетевого взаимодействия.
Там будет запрос на адрес в теле которого в параметрах встретятся твои введенные логин и пароль, например test test
POST HTTP/1.1
Host: forumlocal.ru
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer:
Cookie: w3t_w3t_language=russian
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 136
Cat=&Loginname=test&Loginpass=test&ipbind=1&firstlogin=1&postdata_protection_key=119140b26e3dc99fdc08f2f&buttlogin=%C2%F5%EE%E4
ЗДесь в запросе еще есть параметр postdata_protection_key - надо будет проверить, влияет ли он на успешность залогинивания, если выяснится что он обязателен то сначала надо будет взять страницу входа и распарсить её, найдя в тексте значение postdata_protection_key , там будет что то вида <input type=hidden name=postdata_protection_key value=119140b26e3dc99fdc08f2f>
 В ответ сервер пришлёт куки (и ответ и куки видны в той же панели), самая интересная w3t_w3t_mysess:"d19c688f208f45fa50" или аналогичная
её значение в последующем надо передавать во все запросы к форуму, например в запросе входящих приватов:
GET
Host: forumlocal.ru
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer:
Cookie: w3t_w3t_language=russian; w3t_w3t_myid=10419; w3t_w3t_mysess=d19c688f208f45fa50
Connection: keep-alive
сам код примерно такой же как у асета, только еще после запроса надо извлечь кукисы из ответа.
Headers рекомендую передавать такие какие передаёт обычный браузер, чтобы избежать палева бота.

digenet

спасибо!

khachin

Сообщение удалил

fufa58

мне вполне хватает. алсо пошто ты меня игноришь?

loginData.put("Loginname", login);
loginData.put("Loginpass", password);
loginData.put("rememberme", "1");
loginData.put("firstlogin", "1");
loginData.put("ipbind", "0");
loginData.put("postdata_protection_key", config.POST_PROTECTION_KEY);
loginData.put("buttlogin", "1");

khachin


>>> import requests
>>> import lxml.html
>>> url = "http://forumlocal.ru/login.php"
>>> session = requests.Session()
>>> s = session.get(url)
>>> doctree = lxml.html.document_fromstring(s.text)
>>> inputs = doctree.xpath('/html/body/table[4]/tr/td/table/tr[2]/td/form/input')
>>> for inp in inputs:
... print inp.name
...
Cat
Loginname
Loginpass
rememberme
ipbind
firstlogin
postdata_protection_key
buttlogin

buttlogin не передавал в форму. Потому логин не проходил. Возвращало "Не были заполнены все обязательные поля."
Re алсо: Чтобы со спириткой не путать.

MarizzaMarizza

В общем, благополучно написала скриптик, который берет из списка аэропорты вылета и прилета и ищет по заданному диапазону дат самые дешевые рейсы.
В общем, еще раз всем спасибо, прощаюсь с вами ненадолго - скоро опять приду с вопросами.

kill-still

Ну, ты нас тоже радуй, if you know, what i mean. :o

Temach

Ну, ты нас тоже радуй, if you know, what i mean.
ты про фотку?

sergeikozyr

Под эту задачу затачивался http://cornerapp.com, возможно, там уже есть все, что нужно.

Dasar

Следующее задание )
- получить с хабра все статьи из хаба python или с тегом python
- получить авторов этих статей и всех тех, кто их комментировал
- получить регион из профиля для каждого контакта
- отфильтровать тех, кто из Одессы
- написать каждому вопросы по статье

YUAL

- получить с хабра все статьи из хаба python или с тегом python
гы-гы. буквально на днях видел вакансию на стэковерфлоу в которой это было тестовым заданием. денег кстати не плохо предлагали.

kill-still

Научите лучше девушку xpath или xslt.

stm5872449

Научите лучше девушку xpath или xslt.
:o Лучше не учите девушку этому дерьму! :mad:
Ну серьезно, xslt это худший язык ever. Чтобы это понять, достаточно посмотреть на программу, которая возвращает тот же документ, который был передан ей на вход. Звучит просто, да?

kill-still

А зачем на нём программы писать? :ooo:
А вот для краулеров всяких по-быстренькому скрипт разовый набросать - это можно.

stm5872449

Извини, я не понимаю разницы между словами "программа" и "скрипт".

kill-still

Скрипт = программа, которую запускают один раз.

uncle17

А если я его в крон пропишу, он станет "программой"?

kill-still

Нет, но ты станешь бакланом. Ибо нехрен скрипты пихать в продакшн.
В скрипте позволительно не обрабатывать исключения, ошибки ввода и вообще он может запускаться только в идеальных тепличных условиях под твоим надзором. Потом его надо выбросить.
Потому что быстрее и проще написать его заново, чем хранить всякую хрень.

Dasar

Научите лучше девушку xpath или xslt.
Xslt - мертвая технология. Xml сейчас не в моде.
Xpath полезная штука. Даже не он сам, а понимание его принципов. При разборе html-я, аналог xpath-а очень полезный подход для идентификации элементов.
ps
Интересно, а graphql в простых приложениях применим? Или он прибит гвоздями к большим проектам, бд и т.д.?

kill-still

Xslt - мертвая технология.

ок, уговорил.
Xpath полезная штука.
есть ещё всякие jsonpath и пр.

luna89

Интересно, а graphql в простых приложениях применим? Или он прибит гвоздями к большим проектам, бд и т.д.?
Сейчас есть graphql reference implementation на js. Она позволяет описать типизированную схему, умеет парсить запросы и отвечать на запросы по интроспекции схемы. Бэкенда (то есть кода который получает откуда-то данные) никакого нет, можно реализовать свой простой бэкенд, например http://davidandsuzi.com/writing-a-basic-api-with-graphql/
Если ты интересуешься в контексте этой задачи
Следующее задание )
- получить с хабра все статьи из хаба python или с тегом python
- получить авторов этих статей и всех тех, кто их комментировал
- получить регион из профиля для каждого контакта
- отфильтровать тех, кто из Одессы
- написать каждому вопросы по статье
то тебе graphql не особо помог бы. Он не позволяет делать adhoc запросы. Скорее всего, ты смог бы одним запросом зафетчить все, кроде последнего шага, а фильтровать по городу пришлось бы на клиенте

Dasar

Он не позволяет делать adhoc запросы.
Нафига он такой тогда нужен?

SergeRRRRRR

Xslt - мертвая технология
а что кстати есть на замену? ну например, надо пдфу, или док файл сгенерить. xslt/fo+xml для этого вроде неплохо подходят.

Dasar

а что кстати есть на замену?
любимый язык + xpath
xslt/fo+xml для этого вроде неплохо подходят.
afaik, это единственный продукт, который более-менее использует xslt. имхо, ради одного этого продукта xslt использовать не стоит.

kill-still

Кстати, точно. Все преобразования между разными форматами электронных книг через xslt идут.

SergeRRRRRR

ну я просто часто слышу, что xslt сдохла, но пока чего-то универсального, чтобы и пдфки, и доки, html или просто текст для e-mail рассылок генерить не нашел. Плюс нативная поддержка xslt1 в оракле.
Есть решения для каждой задачи по отдельности.

Marinavo_0507

чем сейчас xslt лучше чем просто взять и написать хоть даже на php? :blush:

kill-still

Ну а зачем в проект на яве или питоне вкорячивать (прости госсподи) пхп?

Marinavo_0507

так напиши на питоне
что там, нет библиотек чтоб сделать pdf или html?

SergeRRRRRR

я в самом деле плохо понимаю вопрос.
есть, например, проект на яве. Задача - генерить динамически пдф и док в зависимости от данных клиента из БД.
Делаешь шаблон для пдф и док в xslt, из базы генеришь xml, натягиваешь одно на другое и отдаешь клиенту.
Причем тут php я не понял.

kill-still

Можно-то оно можно, но вот делать мне нечего больше, кроме как вручную по нодам ходить и в стрингбилдер аппендить. :smirk:

Marinavo_0507

чем генерация xml кодом на java + преобразование xslt лучше чем сразу на java генерация нужного представления на java? разве xslt - более мощный язык?

Marinavo_0507

а чё типа в питоне нет других инструментов? как ты тогда собрался xml генерировать?

SergeRRRRRR

я не понимаю, что значит
чем сразу на java генерация нужного представления на java

Посмотри, например, apache fop.

khachin

Ты общаешься с джавистом. О питоне он только знает, что там есть "%s". Инструменты есть.

luna89

есть, например, проект на яве. Задача - генерить динамически пдф и док в зависимости от данных клиента из БД.
Пдф проще всего генерить конвертацией из html. Docx я генерил просто текстовым шаблонизатором - делал руками в Word эталонный документ, и потом зафигачивал туда инструкции шаблонизатора.

Marinavo_0507

> Посмотри, например, apache fop
а вот рядом тоже apache
без всяких StringBuffer и без XML
http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main...

pilot

Ты общаешься с джавистом. О питоне он только знает, что там есть "%s". Инструменты есть.
Какие? :o
Для получения doc и pdf интересно.

SergeRRRRRR

я видел, поэтому написал, что по отдельности есть средства. xslt же универсален.
да и даже тут, чтобы сгенерить сложную пдфку с кучей таблиц придется до фига кода написать, который хрен потом разберешь, нежели в случае xslt-fo, где все интуитивно понятно.+

Marinavo_0507

дык а чтоб таблицы описать в xml, кучи кода не нужно?

kill-still

Есть библиотеки, которые напрямую из объектов делают.

Marinavo_0507

ну ясно что ты сделаешь таблицу из объектов
но потом же надо оформление писать на xslt - а это разве удобнее чем на java?
я имею в виду всякие штуки: типа объект должен занимать две строки, такое-то поле в первой, а такие-то - во второй в таком-то порядке, а если есть свойство AAA, то надо поставить звёздочку и добавить ещё строчку во вторую таблицу
ну то есть я верю что на java это может быть ещё хуже, чем на xslt (хотя последний вообще непригоден для человека), но на нормальном-то языке вроде питона и пхп точно должно быть проще

SergeRRRRRR

не понимаю, в чем непригодность.
По мне, такие вещи напоминают gwt и иже с ними.
А вынесение статики css,js.html, xml за бизнес-код выглядит логичным.

Marinavo_0507

ну вот на псевдокоде (почти perl/php/js) то что я сказал

foreach $a ($Array1) {
$Table1->add_line(new Line($a->field1, $a->field2));
var $l2 = new Line($a->field4, $a->field3);
if ($a->hasAAA()) {
$l2->add_column('*');
$Table2->add_line(new Line($a->special_attribute()));
}
$Table1->add_line($l2);
}

написать такое с разбегу на почти-XSLT можно? насколько монструозное будет преобразование?
А вынесение статики css,js.html, xml за бизнес-код выглядит логичным. 

в отдельную директорию (пакет) вынеси это преобразование, проблем-то

pilot

Я кстати на первой официальной работе делал тулзу преобразования xslfo в pdf. Называлась XEP - русские делали :o

khachin

Для получения doc и pdf интересно.

Для генерации печатной отчетности (недельная, месячная, квартальная, полугодовая...) юзаю fpdf (правда из-за необходимости логотипа пришлось целый PIL установить, ну, это так, лирика).
По doc-ам ничего сказать не могу. Не было потребности.

pilot

Для генерации печатной отчетности (недельная, месячная, квартальная, полугодовая...) юзаю fpdf (правда из-за необходимости логотипа пришлось целый PIL установить, ну, это так, лирика).
Ну это все поделки, которыми нормальный pdf не сделать. Я знаю один нормальный способ без xslfo - вызывать ТеХ.
По doc-ам ничего сказать не могу. Не было потребности.

Та же самая ботва, нормально работающей библиотеки нет.

SergeRRRRRR

"с разбегу" это зависит от того, как ты часто этим пользуешься и много ли примеров для копипасты.

Marinavo_0507

я и говорю, что без копипасты не осилить
не руками же писать такое
Оставить комментарий
Имя или ник:
Комментарий: