Невозможно получить данные о расписании со своего школьного сайта. Вход через cURL не будет работать - PullRequest
0 голосов
/ 26 декабря 2011

Редактировать: Почему минус один?

Я пытаюсь сделать следующее:

  • Я пытаюсь войти на свой школьный сайт, используя cURL, и захватить расписание, чтобы использовать его для своего ИИ.

Так что мне нужно войти в систему, используя мой пароль и номер, но для формы на школьном сайте также нужен скрытый «токен».

<form action="index.php" method="post">
    <input type="hidden" name="token" value="becb14a25acf2a0e697b50eae3f0f205" />
    <input type="text" name="user" />
    <input type="password" name="password" />
    <input type="submit" value="submit">
</form>

Я могу успешно получить токен. Затем я пытаюсь войти, но это не удается.

// Getting the whole website
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.school.com');
$data = curl_exec($ch);

// Retrieving the token and putting it in a POST
$regex = '/<regexThatWorks>/';
preg_match($regex,$data,$match);
$postfields = "user=<number>&password=<secret>&token=$match[1]";

// Should I use a fresh cURL here?

// Setting the POST options, etc.
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

// I won't use CURLOPT_RETURNTRANSFER yet, first I want to see results. 
$data = curl_exec($ch);

curl_close($ch); 

Ну ... это не работает ...

  • Возможно ли, что токен меняется каждый curl_exec? Поскольку сайт не распознает скрипт во второй раз ...
  • Должен ли я создать новый экземпляр cURL (?) Для второй части?
  • Есть ли другой способ получить токен в пределах 1 соединения?
  • печенье

Ответы [ 3 ]

1 голос
/ 26 декабря 2011

Вот как я это решил. Вероятно, проблема заключалась в том, что они не использовали файлы cookie. Тем не менее, это, вероятно, «некрасивый» код, поэтому любые улучшения приветствуются!

// This part is for retrieving the token from the hidden field.
// To be honest, I have no idea what the cookie lines actually do, but it works.
$getToken= curl_init();
curl_setopt($getToken, CURLOPT_URL, '<schoolsite>');       // Set the link
curl_setopt($getToken, CURLOPT_COOKIEJAR, 'cookies.txt');  // Magic
curl_setopt($getToken, CURLOPT_COOKIEFILE, 'cookies.txt'); // Magic
curl_setopt($getToken, CURLOPT_RETURNTRANSFER, 1);         // Return only as a string
$data = curl_exec($token);                                 // Perform action

// Close the connection if there are no errors
if(curl_errno($token)){print curl_error($token);}
else{curl_close($token);} 

// Use a regular expression to fetch the token
$regex = '/name="token" value="(.*?)"/';
preg_match($regex,$data,$match);

// Put the login info and the token in a post header string
$postfield = "token=$match[1]&user=<number>&paswoord=<mine>";
echo($postfields);

// This part is for logging in and getting the data.
$site = curl_init();
curl_setopt($site, CURLOPT_URL, '<school site');
curl_setopt($site, CURLOPT_COOKIEJAR, 'cookies.txt');    // Magic
curl_setopt($site, CURLOPT_COOKIEFILE, 'cookies.txt');   // Magic
curl_setopt($site, CURLOPT_POST, 1);                     // Use POST (not GET)
curl_setopt($site, CURLOPT_POSTFIELDS, $postfield);      // Insert headers
$forevil_uuh_no_GOOD_purposes = curl_exec($site);        // Output the results

// Close connection if no errors           
if(curl_errno($site)){print curl_error($site);}
else{curl_close($site);} 
1 голос
/ 26 декабря 2011

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

Создание собственного класса запросов позволит вам реализовать запрос curl так, как вам нужно.Создавая свой собственный класс ответа, вы можете помочь вам получить доступ к синтаксическому анализу возвращенного HTML.

Это простой пример использования некоторых классов, которые я создал для демонстрации:

# simple get request
$request = new MyRequest('http://hakre.wordpress.com/');
$response = new MyResponse($request);
foreach($response->xpath('//div[@id="container"]//div[contains(normalize-space(@class), " post ")]') as $node)
{
    if (!$node->h2->a) continue;
    echo $node->h2->a, "\n<", $node->h2->a['href'] ,">\n\n"; 
}

Это будетвернуть мои сообщения в блогах:

Will Automattic join Dec 29 move away from GoDaddy day?
<http://hakre.wordpress.com/2011/12/23/will-automattic-join-dec-29-move-away-from-godaddy-day/>

PHP UTF-8 string Length
<http://hakre.wordpress.com/2011/12/13/php-utf-8-string-length/>

Title belongs into Head
<http://hakre.wordpress.com/2011/11/02/title-belongs-into-head/>

...

Отправив запрос на получение, легко и просто, ответ можно легко получить с помощью выражения xpath (здесь SimpleXML ).XPath может быть полезен для выбора токена в поле формы, так как он позволяет вам запрашивать данные документа легче, чем с помощью регулярного выражения.

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

# simple post request
$request = new MyRequest('https://example.wordpress.com/wp-login.php');
$postFields = array(
    'log' => 'username', 
    'pwd' => 'password',
);
$request->setPostFields($postFields);
$response = new MyResponse($request->returnHeaders(1)->execute());
echo (string) $response; # output to view headers

Учитывая ваш сценарий, вы можете отредактировать свой собственный класс запросов, чтобы лучше справляться с тем, что вам нужно.Мой уже использует куки, как вы их тоже.Поэтому некоторый код, основанный на этих классах для вашего сценария, может выглядеть следующим образом:

# input values
$url = '<schoolsite>';
$user  = '<number>';
$password = '<secret>';

# execute the first get request to obtain token
$response = new MyResonse(new MyRequest($url));
$token = (string) $response->xpath('//input[@name="token"]/@value');

# execute the second login post request
$request = new MyRequest($url);
$postFields = array(;
    'user' => $user, 
    'password' => $password,
    'token' => $token
);
$request->setPostFields($postFields)->execute();

Demo и код в виде gist .

Если вы хотитечтобы еще больше улучшить это, следующим шагом будет то, что вы создадите себе класс для «школьной службы», из которой вы будете извлекать расписание:

class MySchoolService
{
    private $url, $user, $pass;
    private $isLoggedIn;
    public function __construct($url, $user, $pass)
    {
        $this->url = $url;
        ...
    }
    public function getSchedule()
    {
        $this->ensureLogin();

        # your code to obtain the schedule, e.g. in form of an array.
        $schedule = ...

        return $schedule;
    }
    private function ensureLogin($reuse = TRUE)
    {
        if ($reuse && $this->isLoggedIn) return;

        # execute the first get request to obtain token
        $response = new MyResonse(new MyRequest($this->url));
        $token = (string) $response->xpath('//input[@name="token"]/@value');

        # execute the second login post request
        $request = new MyRequest($this->url);
        $postFields = array(;
            'user' => $this->user, 
            'password' => $this->password,
            'token' => $token
        );
        $request->setPostFields($postFields)->execute();

        $this->isLoggedIn = TRUE;
    }
}

После того, как вы красиво завершили запрос /Логика ответа в ваш класс MySchoolService. Вам нужно только создать его экземпляр с правильной конфигурацией, и вы можете легко использовать его на своем веб-сайте:

$school = new MySchoolService('<schoolsite>', '<number>', '<secret>');
$schedule = $school->getSchedule();

Ваш основной сценарий использует только MySchoolService.

MySchoolService заботится об использовании объектов MyRequest и MyResponse.

MyRequest заботится о выполнении HTTP-запросов (в данном случае cUrl) с файлами cookie и тому подобным.

MyResponse немного помогает при разборе HTTP-ответов.

Сравните это со стандартным интернет-браузером:

Browser: Handles cookies and sessions, does HTTP requests and parses responses.

MySchoolService: Handles cookies and sessions for your school, does HTTP requests and parses responses.

Итак, теперь у вас есть школьный браузер, который делает то, что делаетты хочешь.Если вам нужно больше опций, вы можете легко их расширить.

Надеюсь, это полезно, отправной точкой было предотвращение повторной записи одних и тех же строк кода cUrl, а также улучшение интерфейсаразобрать возвращаемые значения.MySchoolService - это сахар, который облегчает работу с вашим собственным сайтом / кодом приложения.

1 голос
/ 26 декабря 2011

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

...