我正在尝试为 Strava.cz 制作第三方午餐订购系统。我已经制作了一个应该这样做的图书馆。除 strava_czChoose 函数外,一切正常。它不会引发错误,但什么也不做。他们的服务器基于 Windows ASPX,因此很难理解所有传输的数据。这是整个代码:
<?php
/**
* Additional function for DOMDocument
* * * * *
* @param DOMDocument $DOMDocument Document where you want to search
* @patam string $className Name of the class you are searching of
* * * * *
*/
function getElementsByClassName(\DOMDocument $DOMDocument, $className) {
$Elements = $DOMDocument->getElementsByTagName("*");
$Matched = array();
for($i=0;$i<$Elements->length;$i++) {
if(in_array($ClassName, explode(' ', $Elements->item($i)->attributes->getNamedItem('class')->nodeValue))) {
$Matched[]=$Elements->item($i);
}
}
return $Matched;
}
$strava_czHeader="User-Agent:(none; StravaCekujNET; Linux x86_64; rv:1.0)\r\nAccept:(text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8)\r\nAccept-Language:(cs,sk;q=0.8,en;q=0.6,en-gb;q=0.4,en-us;q=0.2)\r\nAccept-Encoding:(gzip, deflate)\r\nDNT:(1)\r\nConnection:(keep-alive)\r\n";
$strava_czHandle="n/a";
/**
* * * * * * * * * * * * * * * *
* Přihlášení (strava_czLogin) *
* * * * * * * * * * * * * * * *
* @param int|string $machine Zařízení (4 číslice, string v případě, že začíná nulou)
* @param int|string $user Uživatel (10 číslic, string v případě, že začíná nulou)
* @param string $pass Heslo pro přihlášení
* * * * *
*/
function strava_czLogin($machine,$user,$pass){
global $strava_czHeader;
global $strava_czHandle;
//Zašle první požadavek > $dom
$src = file_get_contents('http://m.strava.cz/Stravnik/formprihlaseni.aspx',false,stream_context_create(array('http'=>array('header' => $strava_czHeader))));
$dom = new domDocument; //Vytvoří DOM
$doc->strictErrorChecking = false;
$src = mb_convert_encoding($src, 'HTML-ENTITIES', "UTF-8");
$dom->loadHTML($src); //Načte HTML
unset($http_response_header, $src); //Uvolní paměť
//Zpracuje přijatá data a zjistí klíč > $key
$query['viewstate'] = $dom->getElementById('__VIEWSTATE')->getAttribute('value');
$query['eventvalidation'] = $dom->getElementById('__EVENTVALIDATION')->getAttribute('value');
$key = '?__EVENTTARGET'.
'&__EVENTARGUMENT'.
'&__VIEWSTATE='.urlencode($query['viewstate']).
'&__EVENTVALIDATION='.urlencode($query['eventvalidation']).
'&ctl00%24ContentPlaceHolder1%24txtZarizeni='.urlencode($machine).
'&ctl00%24ContentPlaceHolder1%24txtUzivatel='.urlencode($user).
'&ctl00%24ContentPlaceHolder1%24txtHeslo='.urlencode($pass).
'&ctl00%24ContentPlaceHolder1%24butOdeslat=Odeslat';
unset($dom, $query); //Uvolní paměť
//Zašle požadavek > $src, $http_response_header
$src = file_get_contents('http://m.strava.cz/Stravnik/formprihlaseni.aspx'.$key,false,stream_context_create(array('http'=>array('header' => $strava_czHeader))));
unset($key, $src); //Uvolní paměť
//Zpracuje přijaté sušenky (mňam!)
$i = 1;
$strava_czHandle = array();
$strava_czHandle['cookies'] = "";
foreach ($http_response_header as $value) {
$preg = preg_match('/^Set-Cookie:\s*.[^=]*=.[^;]*/m', $value, $matches);
if ($preg) {
foreach ($matches as $match) {
$strava_czHandle['cookies'] .= substr($match, 12); //Zápis do handleru
//Substring proto, aby se do handleru nezapisovalo i "SetCookie: "
}
}
}
unset($i, $http_response_header, $matches, $match, $value); //Uvolní paměť
//Případně vyhodí chybu
if ($strava_czHandle['cookies']==""){throw new Exception("noResult");}
}
/**
* * * * * * * * * * * * * * * *
* Odhlášení (strava_czLogout) *
* * * * * * * * * * * * * * * *
*/
function strava_czLogout(){
global $strava_czHandle;
if ($strava_czHandle=="n/a") {throw new Exception("notLogged");}
//Zašle požadavek
$src = file_get_contents('http://m.strava.cz/Stravnik/odhlaseni.aspx',false,stream_context_create(array('http'=>array('header' => $strava_czHeader."Cookie: ".$strava_czHandle['cookies']."\r\n"))));
//Zkontroluje správnost přijatých dat
if (preg_match('/<form.*[^>]action="Default.aspx".*[^>]>/m',$src)){
$strava_czHandle="n/a";
} else {
throw new Exception("unknownError");
}
}
/**
* * * * * * * * * * * * * * * * * * * * *
* Získání jídelníčku (strava_czGetList) *
* * * * * * * * * * * * * * * * * * * * *
*/
function strava_czGetList(){
global $strava_czHeader;
global $strava_czHandle;
if (!$strava_czHandle||$strava_czHandle=="n/a") {throw new Exception("notLogged");}
//Zašle požadavek > $dom
$src = file_get_contents('http://m.strava.cz/Stravnik/objednavky.aspx',false,stream_context_create(array('http'=>array('header' => $strava_czMozHeader."Cookie:".$strava_czHandle['cookies']."\r\n"))));
$dom = new domDocument; //Vytvoří DOM
$doc -> strictErrorChecking = FALSE;
$src = mb_convert_encoding($src, 'HTML-ENTITIES', "UTF-8");
$dom -> loadHTML($src); //Načte HTML
unset($http_response_header, $src); //Uvolní paměť
//Zpracuje přijatá data > $nodeArray, $xpath
$tbl = $dom -> getElementById('tblObjednavky') -> childNodes;
$nodeArray=array(); $j=-1; $class = null;
foreach ($tbl as $item) {
if (($item -> getAttribute('class')) === 'tblObjednavkyDatum') {$j++;}
$nodeArray[$j][] = $item;
}
$xpath = new DOMXPath($dom);
unset($dom, $tbl, $j, $class, $item);
/*
Vytvořeno dvourozměrné pole. První rozměr určuje den a druhý konkrétní node
(0 pro řádek s datem, vyšší číslo pro řádek s jídlem).
*/
//Roztřídí přijatá data > $result
$result = array();
$i = 0;
foreach ($nodeArray as $item) {
$result[$i]['chosen'] = null;
$result[$i]['choosable'] = false;
$result[$i]['day'] = null;
$j = -1;
foreach ($item as $subitem) {
if ($j > -1) {
//Nastaví hodnoty, které jsou pro každou volbu individuální
$result[$i]['name'][$j] = substr($xpath -> evaluate('./td[4]', $subitem) -> item(0) -> textContent, 4);
/*
Lowercase
Všechny bílé znaky převést na mezeru a zakázat více mezer za sebou (chování jako HTML bez white-space:pre)
Za každou tečku a čárku, za kterou není mezera, přidat mezeru.
*/
$result[$i]['name'][$j] = preg_replace('([\.,])', '$0 ', $result[$i]['name'][$j]);
$result[$i]['name'][$j] = preg_replace('/\s+/m',' ', mb_strtolower($result[$i]['name'][$j], 'utf-8'));
if ($xpath -> evaluate('./td[2]/img', $subitem) -> length) {$result[$i]['chosen'] = $j;}
$x = $xpath -> evaluate('./td[3]/span/input', $subitem);
if ($x -> length) {
$result[$i]['choosable'] = true;
$result[$i]['day'] = $x -> item(0) -> getAttribute('name');
$result[$i]['lunch'][$j] = $x -> item(0) -> getAttribute('value');
}
}
$j++;
}
//Nastaví hodnoty, které platí pro celý den
$result[$i]['date'] = $item[0] -> textContent;
/* TODO Převést datum na DD/MM/YYYY */
$i++;
}
//Vrátí výsledné hodnoty
if ($result == array()) {throw new Exception("noResult");} else {return $result;}
}
/**
* * * * * * * * * * * * * * * * * * * *
* Objednávání jídel (strava_czChoose) *
* * * * * * * * * * * * * * * * * * * *
*/
function strava_czChoose($list) {
global $strava_czHeader;
global $strava_czHandle;
if (!$strava_czHandle||$strava_czHandle=="n/a") {throw new Exception("notLogged");}
//Pošle první požadavek (získá ty mrkvosofťácký "chujoviny", jak by řekl Keby) > $dom, $list
$src = file_get_contents('http://m.strava.cz/Stravnik/objednavky.aspx',false,stream_context_create(array('http'=>array('header' => $strava_czMozHeader."Cookie:".$strava_czHandle['cookies']."\r\n"))));
$dom = new domDocument; //Vytvoří DOM
$doc->strictErrorChecking = false;
$src = mb_convert_encoding($src, 'HTML-ENTITIES', "UTF-8");
$dom->loadHTML($src); //Načte HTML
unset($http_response_header,$src);
//Zpracuje data a zjistí klíč > $key, $list
$query['viewstate'] = $dom->getElementById('__VIEWSTATE')->getAttribute('value');
$query['eventvalidation'] = $dom->getElementById('__EVENTVALIDATION')->getAttribute('value');
$key = '?_EVENTTARGET=butOdeslat'.
'&_EVENTARGUMENT'.
'&_VIEWSTATE='.urlencode($query['viewstate']).
'&_EVENTVALIDATION='.urlencode($query['eventvalidation']);
unset($dom,$query);
//Ze zadání vytvoří string dotazu > $data, $key
$data = '';
foreach ($list as $day => $lunch) {
$data .= '&'.urlencode($day).'=radObjednavka'.urlencode($lunch);
}
var_dump('http://m.strava.cz/Stravnik/objednavky.aspx'.$key.$data);
//Pošle druhý požadavek (odešle objednávku), případně vyhodí error
file_get_contents('http://m.strava.cz/Stravnik/objednavky.aspx'.$key.$data,false,stream_context_create(array('http'=>array('header' => $strava_czMozHeader."Cookie:".$strava_czHandle['cookies']."\r\n"))));
if (preg_match('/500/',$http_response_header)) {throw new Exception("unknownError");}
}
try {strava_czLogin(/*secret*/);}
catch (Exception $e) {exit("</div><div>Přihlášení se nezdařilo, chyba: ".($e -> getMessage()));}
try {$r=strava_czGetList();}
catch (Exception $e) {exit("</div><div>Zjištení jídel se nezdařilo, chyba: ".($e -> getMessage()));}
try {strava_czChoose(array('2013-03-121' => 'P754'));}
catch (Exception $e) {exit("</div><div>Chyba při odesílání objednávek: ".($e -> getMessage()));}
try {strava_czLogout();}
catch (Exception $e) {exit("</div><div>Odhlaseni se nezdařilo, chyba: ".($e -> getMessage()));}
var_dump($r);
?>
我不知道怎么了。抱歉评论,他们是捷克语,你可以使用谷歌翻译,但它的翻译不是doubleplusgood。谢谢你的帮助,m93a
编辑:我发现如果服务器返回 HTTP 302,这是一个可接受的选择。我得到 HTTP 200。我什至尝试使用 POST 而不是 GET,但我仍然得到 200。