The author's guzzle
code is like this:
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\RequestException;
class getSegmentfaultArticle extends Command
{
protected $signature = 'segmentfault:artical';
protected $description = '获取 Segmentfault 文章的信息';
protected $client;
protected $crawler;
protected $user = [];
protected $login_page_url = '/user/login';
protected $login_url = '/api/user/login?_=775250c435a29c7a335a11ab2f641423';
protected $sessionId = 'web2~04u8m9qfpnt6abl6ljuqae59l0';
protected $my_seg_home_url = '/u/greenlightt/articles';
public function __construct(Crawler $crawler) {
parent::__construct();
$this->client = new Client([
'base_uri' => 'https://segmentfault.com',
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0',
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
],
'cookies' => true,
'http_errors' => true,
]);
$this->crawler = $crawler;
// 获取登录名及密码
$this->user['email'] = config('services.segmentfault.email');
$this->user['password'] = config('services.segmentfault.password');
}
public function handle() {
// 较验 auth
if (is_null($this->user['email']) || is_null($this->user['password'])) {
$this->error('请在 .env 文件填写 Segmentfault 账号及密码');
return;
}
// 登录获取 cookies
$this->client->request('GET', $this->login_page_url);
$this->updateCookies();
$response = $this->client->request('POST', $this->login_url,
array(
'form_params' => [
'username' => $this->user['email'],
'password' => $this->user['password'],
],
'headers' => [
'Referer' => '/user/login'
]
)
);
}
/*
* 修改 Cookie 中的 PHPSESSID 值
*/
protected function updateCookies() {
$config = $this->client->getConfig();
$cookie = $config['cookies']->toArray()[0];
$cookie['Value'] = $this->sessionId;
$config['cookies']->setCookie(
new SetCookie($cookie)
);
}
}
The result error is as follows:
三叔2017-06-13 09:26:33
login?_=The following token is not fixed, you have to manually take it out from window.SF.token.
In addition, the cookie is not included when requesting, so SF judges that you are making an illegal request, 404.
Since the author believes that the token after _ is an arbitrary field, let’s verify it. The following is the code that runs correctly (without laravel)
Because the SF token has obfuscated fields, PHP should not be able to simply parse it out, so we directly use shell_exe to call node to obtain the token.
<?php
require_once __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\RequestException;
$login_page_url = '/user/login';
$login_url = '/api/user/login?_=';
$client = new Client([
'base_uri' => 'https://segmentfault.com',
'headers' => [
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0',
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
],
'cookies' => true,
'http_errors' => true,
]);
$user = [
'email' => '1@qq.com',
'password' => '2333',
];
$response = $client->request('GET', $login_page_url);
$body = (string) $response->getBody();
preg_match_all('/<script[\s\S]*?<\/script>/', $body, $matches);
$script = null;
foreach ($matches[0] as $value) {
if (strpos($value, 'w.SF.token') !== false) {
$script = $value;
break;
}
}
$script = str_replace(['<script>', '</script>'], '', $script);
file_put_contents(__DIR__ . '/test.js', 'var window = {};' . "\r\n" . $script . "\r\n" . 'console.log(window.SF.token);');
$token = shell_exec('/usr/local/bin/node test.js' . " 2>&1");
$token = trim($token);
// get cookie
$config = $client->getConfig();
$cookie = $config['cookies']->toArray()[0];
$cookieJar = CookieJar::fromArray([
$cookie['Name'] => $cookie['Value'],
], $cookie['Domain']);
try {
$response = $client->request('POST', $login_url . $token,
array(
'cookies' => $cookieJar,
'form_params' => [
'username' => $user['email'],
'password' => $user['password'],
],
'headers' => [
'Referer' => '/user/login',
],
)
);
} catch (RequestException $e) {
echo $e->getMessage();
}
echo (string) $response->getBody();
Output result: