Php 无法从我的学校网站获取我的时间表数据。使用cURL-won';行不通

Php 无法从我的学校网站获取我的时间表数据。使用cURL-won';行不通,php,curl,screen-scraping,Php,Curl,Screen Scraping,编辑:为什么是负数 我想做的是: 我正在尝试使用cURL登录我的学校网站,并抓取时间表,将其用于我的AI 因此,我需要使用我的通行证和号码登录,但学校网站上的表单也需要一个隐藏的“令牌” <form action="index.php" method="post"> <input type="hidden" name="token" value="becb14a25acf2a0e697b50eae3f0f205" /> <input type="

编辑:为什么是负数

我想做的是:

  • 我正在尝试使用cURL登录我的学校网站,并抓取时间表,将其用于我的AI
因此,我需要使用我的通行证和号码登录,但学校网站上的表单也需要一个隐藏的“令牌”

<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); 
//获取整个网站
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,'http://www.school.com');
$data=curl\u exec($ch);
//检索令牌并将其放在帖子中
$regex='/';
preg_match($regex,$data,$match);
$postfields=“user=&password=&token=$match[1]”;
//我应该用一个新的卷发吗?
//设置POST选项等。
卷曲设置($ch,卷曲设置桩,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$POSTFIELDS);
//我还不会使用CURLOPT_RETURNTRANSFER,首先我想看看结果。
$data=curl\u exec($ch);
卷曲关闭($ch);
嗯。。。它不起作用

  • 是否有可能每次curl\u exec都会更改令牌?因为站点第二次无法识别脚本
  • 我应该为第二部分创建一个新的cURL实例(?)
  • 是否有其他方法在1个连接内获取令牌
  • 饼干

您收到的错误消息是什么?独立于此;您学校的网站可能会检查推荐人标题,并确保请求来自其登录页面(一个假装是…)的应用程序。

您收到的错误消息是什么?独立于此;你学校的网站可能会检查推荐人的标题,并确保请求来自(假装是…)其登录页面。

我就是这样解决的。问题可能是“不使用cookies”部分。 不过,这可能是“丑陋”的代码,所以欢迎任何改进

// 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);} 
//此部分用于从隐藏字段中检索令牌。
//老实说,我不知道cookie行实际上做了什么,但它是有效的。
$getToken=curl_init();
curl_setopt($getToken,CURLOPT_URL,');//设置链接
curl_setopt($getToken,CURLOPT_COOKIEJAR,'cookies.txt');//魔术
curl_setopt($getToken,CURLOPT_COOKIEFILE,'cookies.txt');//魔术
curl_setopt($getToken,CURLOPT_RETURNTRANSFER,1);//仅作为字符串返回
$data=curl_exec($token);//行动
//如果没有错误,请关闭连接
if(curl_errno($token)){print curl_error($token);}
else{curl_close($token);}
//使用正则表达式获取标记
$regex='/name=“token”value=“(.*?)/”;
preg_match($regex,$data,$match);
//将登录信息和令牌放入post标题字符串中
$postfield=“令牌=$match[1]&user=&paswoord=”;
echo($postfields);
//此部分用于登录和获取数据。
$site=curl_init();

curl_setopt($site,CURLOPT_URL,”我就是这样解决的。问题可能是“不使用cookies”部分。 不过,这可能是“丑陋”的代码,所以欢迎任何改进

// 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);} 
//此部分用于从隐藏字段中检索令牌。
//老实说,我不知道cookie行实际上做了什么,但它是有效的。
$getToken=curl_init();
curl_setopt($getToken,CURLOPT_URL');//设置链接
curl_setopt($getToken,CURLOPT_COOKIEJAR,'cookies.txt');//魔术
curl_setopt($getToken,CURLOPT_COOKIEFILE,'cookies.txt');//Magic
curl_setopt($getToken,CURLOPT_RETURNTRANSFER,1);//仅作为字符串返回
$data=curl_exec($token);//执行操作
//如果没有错误,请关闭连接
if(curl_errno($token)){print curl_error($token);}
else{curl_close($token);}
//使用正则表达式获取标记
$regex='/name=“token”value=“(.*?)/”;
preg_match($regex,$data,$match);
//将登录信息和令牌放入post标题字符串中
$postfield=“令牌=$match[1]&user=&paswoord=”;
echo($postfields);
//此部分用于登录和获取数据。
$site=curl_init();

curl_setopt($site,CURLOPT_URL,“当你在构建一个scraper时,你可以创建你自己的类来处理你在你的域中需要做的事情。你可以从创建你自己的一组处理你需要处理的请求和响应类开始

创建自己的请求类将允许您按照需要的方式实现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"; 
}
考虑到您的场景,您可能希望编辑自己的请求类以更好地处理您的需要,我的请求类在您使用cookies时也已经使用了cookies。因此,您的场景中基于这些类的一些代码可能如下所示:

# 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();
在您将请求/响应逻辑很好地包装到您的
MySchoolService
类中后,您只需使用适当的配置对其进行实例化,就可以轻松地在网站中使用它:

$school = new MySchoolService('<schoolsite>', '<number>', '<secret>');
$schedule = $school->getSchedule();
因此,您现在的脚本中有一个学校浏览器,它可以满足您的需要。如果您需要更多选项,您可以轻松地扩展它


我希望这是有帮助的,其出发点是防止重复编写相同的cUrl代码行,并为您提供更好的界面来解析返回值。
MySchoolService
是一些放在上面的糖,可以让您在自己的网站/应用程序代码中轻松处理。

在构建刮板时,您可以创建自己的类来处理域中需要执行的操作。您可以从创建自己的一组请求和响应类开始,这些类处理您需要处理的操作

创建您自己的请求类将允许您以您需要的方式实现curl请求。创建您自己的响应类可以帮助您访问/解析返回的HT
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;
    }
}
$school = new MySchoolService('<schoolsite>', '<number>', '<secret>');
$schedule = $school->getSchedule();
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.