筆者的guzzle
程式碼是這樣的:
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)
);
}
}
結果報錯如下:
#
三叔2017-06-13 09:26:33
login?_=後面的token不是固定的,你要手動從window.SF.token裡面取出來。
另外請求的時候cookie也沒有帶,所以SF判斷你是非法請求,404.
鑑於樓主認為_後面的token屬於隨意的字段,下面來驗證一下,以下給出運行正確的代碼(沒有用laravel)
因為SF的token有混淆字段,php應該不能簡單的解析出來,所以直接用shell_exe呼叫node來取得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();
輸出結果: