使用cURL、PHP和Twitter而不使用API的逻辑
我有这个代码,它将使用cURL、PHP和Twitter而不使用API的逻辑,php,curl,twitter,Php,Curl,Twitter,我有这个代码,它将cookies保存在.txt文件中,并使用Twitter验证用户 <?php require_once 'class/Cookies.php'; $cookie = []; $username = 'formUser'; $password = 'formPass'; $index_url = 'https://twitter.com'; $token = curl_init(); curl_setopt_array($token, [ CURLOP
cookies
保存在.txt
文件中,并使用Twitter验证用户
<?php
require_once 'class/Cookies.php';
$cookie = [];
$username = 'formUser';
$password = 'formPass';
$index_url = 'https://twitter.com';
$token = curl_init();
curl_setopt_array($token, [
CURLOPT_URL => $index_url,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
//CURLOPT_COOKIEFILE => __DIR__ . DIRECTORY_SEPARATOR . 'cookies' . DIRECTORY_SEPARATOR . $username . '.txt',
CURLOPT_COOKIEJAR => __DIR__ . DIRECTORY_SEPARATOR . 'cookies' . DIRECTORY_SEPARATOR . $username . '.txt',
CURLOPT_COOKIESESSION => true,
CURLOPT_REFERER => $index_url,
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => ['Cookie:' . http_build_query($cookie, '', ';') . ';'],
CURLOPT_HEADERFUNCTION => function ($curl, $header) use (&$cookie) {
if (stripos($header, 'Set-Cookie:') === 0) {
if (preg_match('/Set-Cookie:\s?(.*?)=(.*?);/i', $header, $matches)) {
$cookie[$matches[1]] = urldecode($matches[2]);
}
}
return strlen($header);
}
]
);
$access = curl_exec($token);
preg_match('/value="(.*?)" name="authenticity_token"/', $access, $matches);
$authenticity_token = $matches[1];
//var_dump($authenticity_token);
$session_post = "session[username_or_email]=$username&session[password]=$password&return_to_ssl=true&scribe_log=&redirect_after_login=%2F&authenticity_token=$authenticity_token";
$session_url = 'https://twitter.com/sessions';
curl_setopt_array($token, [
CURLOPT_URL => $session_url,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $session_post,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Content-type: application/x-www-form-urlencoded",
'Cookie: '. http_build_query($cookie, '', ';').';'
],
CURLOPT_USERAGENT => $_SERVER['HTTP_USER_AGENT'],
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 2,
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
CURLOPT_POSTREDIR => 2,
CURLOPT_AUTOREFERER => 1
]
);
$auth = curl_exec($token);
var_dump($cookie);
if (isset($cookie['auth_token']))
{
$twid = filter_var($cookie['twid'], FILTER_SANITIZE_NUMBER_INT);
Cookies::set('login_token', $cookie['ct0']);
Cookies::set('kdt', $cookie['kdt']);
Cookies::set('user_id', $twid);
Cookies::set('auth_token', $cookie['auth_token']);
Cookies::set('username', $username);
echo json_encode(array(
"status" => "success",
"message" => "Authentication successful, we are redirecting you.",
));
}
else
{
echo json_encode(
array(
"status" => "error",
'message'=> "Unable to authenticate with Twitter.",
));
}
答复:
C:\wamp64\www\brfollow\api\follow.php:32:string 'HTTP/1.1 400 Bad Request
content-length: 62
content-type: application/json; charset=utf-8
date: Fri, 07 Jul 2017 08:09:54 GMT
server: tsa_d
set-cookie: guest_id=v1%3A149941499419523606; Domain=.twitter.com; Path=/; Expires=Sun, 07-Jul-2019 08:09:54 UTC
strict-transport-security: max-age=631138519
x-connection-hash: 9e951d1215095efa246c5b852acd2e8a
x-response-time: 131
x-tsa-request-body-time: 0
{"errors":[{"code":215,"message":"Bad Authentication data."}]}' (length=472)
你必须使用
CURLOPT_COOKIEJAR => __DIR__ . DIRECTORY_SEPARATOR . 'cookies' . DIRECTORY_SEPARATOR . $username . '.txt',
在您的第二个请求中也是如此。您必须使用
CURLOPT_COOKIEJAR => __DIR__ . DIRECTORY_SEPARATOR . 'cookies' . DIRECTORY_SEPARATOR . $username . '.txt',
在您的第二个请求中也是如此。首先,请注意现有代码: 不要对
GET
和POST
请求使用CURLOPT_CUSTOMREQUEST。对于GET
,使用CURLOPT\u HTTPGET=>true
(还要注意,GET是libcurl的默认请求),对于POST
请求,使用CURLOPT\u POST=>true
此行preg_match('/value=“(.*)”name=“authenticity_token”/',$access,$matches)代码>
如果在值和名称之间放置任何附加属性,则将中断,
如果他们只是把名字移到值后面,它甚至会断开,它会断开
如果他们在注释中放入一个相似的字符串(
-style),如果他们只是在值和名称之间加一个空格,它甚至会断开,
一种更为稳健的方法是:
$authenticity_token=(new DOMXpath(@DOMDocument::loadHTML($access)))->query("//input[@name='authenticity_token']")->item(0)->getAttribute("value");
在这一行中,您会犯同样的错误3次:
$session_post = "session[username_or_email]=$username&session[password]=$password&return_to_ssl=true&scribe_log=&redirect_after_login=%2F&authenticity_token=$authenticity_token";
您不需要对$username、$password和$U令牌进行URL编码。这意味着,如果这3个字符中的任何一个在application/x-www-urlencoded
格式中包含任何具有特殊意义的字符,服务器将获得错误的数据(包括空格、&
、=
、Æ
、Ø
、以及许多其他字符),简单的解决方案是在它们上使用urlencode(),漂亮的解决方案是使用http_build_query生成字符串,如下所示:
$session_post = http_build_query ( array (
'session' => array (
'username_or_email' => $username,
'password' => $password
),
'return_to_sssl' => true,
'scribe_log' => '',
'redirect_after_login' => '/',
'authenticity_token' => $authenticity_token
) );
你在这一行也犯了同样的错误:
CURLOPT_POSTFIELDS => 'screen_name=' . $username,
这一行一定是错误添加的:
CURLOPT_HTTPHEADER => [
"Content-type:text/html;charset=utf-8",
],
它是一个GET请求,没有请求主体,因此没有内容类型
,因为没有内容,所以不可能有内容类型头声明,请去掉它
这条线
CURLOPT_ENCODING => "gzip"
如果curl不是用gzip编译的,并且服务器实际决定使用gzip(更具体地说,您将获得无法理解的二进制数据),并且您没有提供任何代码来实际处理gzip二进制数据,那么将中断您的代码。一种更为稳健的方法是将其设置为emptystring“”
,然后curl将提供libcurl编译的所有编码,并将动态地为您对其进行反编码(包括gzip,如果在中编译的话)。它通常是gzip
和deflate
,但它也是未来的证明,因为它将自动添加任何未来的编码)
这条线
"Content-type: application/x-www-form-urlencoded",
不要自动添加此标题。libcurl将自动检测应用程序/x-www-urlcoded
和多部分/表单数据
编码,并自动设置适当的内容类型
标题。与您不同的是,libcurl在执行此操作时不会打字
现在,下一步是获取所有当前关注者,并发送关注请求。你说你不想使用api,但实际上没有办法避免它(除了入侵twitter数据库,ofc),甚至tiwtter的javascript“关注”button使用api。好消息是,您可以使用twitter的javascript api令牌,从而不必使用您自己的令牌。这在理论上听起来很容易,但实际上并非如此。尽管如此,这里有一个hhb_curl的示例实现(来自),获取关注者列表,并使用Twitter自己的api密钥(自动提取)向每个关注者发送关注请求:
首先是关于现有代码的一些注释:
对于GET
和POST
请求,不要使用CURLOPT\u CUSTOMREQUEST。对于GET
,使用CURLOPT\u HTTPGET=>true
(还要注意GET是libcurl的默认请求),对于POST
请求,使用CURLOPT\u POST=>true
此行preg_match('/value=“(.*)”name=“authenticity_token”/',$access,$matches);
如果在值和名称之间放置任何附加属性,则将中断,
如果他们只是把名字移到值后面,它甚至会断开,它会断开
如果他们在注释中放入一个相似的字符串(
-style),如果他们只是在值和名称之间加一个空格,它甚至会断开,
一种更为稳健的方法是:
$authenticity_token=(new DOMXpath(@DOMDocument::loadHTML($access)))->query("//input[@name='authenticity_token']")->item(0)->getAttribute("value");
在这一行中,您会犯同样的错误3次:
$session_post = "session[username_or_email]=$username&session[password]=$password&return_to_ssl=true&scribe_log=&redirect_after_login=%2F&authenticity_token=$authenticity_token";
您不需要对$username、$password和$authenticity\u令牌进行urlencode编码。这意味着,如果这三个字符中的任何一个在application/x-www-urlencoded
格式中包含具有特殊意义的字符,服务器将获取错误的数据(包括空格、&
、=
、[
,Æ
,Ø
,Å
,以及许多其他字符),简单的解决方案是对它们使用urlencode(),而漂亮的解决方案是使用http_build_query生成字符串,如下所示:
$session_post = http_build_query ( array (
'session' => array (
'username_or_email' => $username,
'password' => $password
),
'return_to_sssl' => true,
'scribe_log' => '',
'redirect_after_login' => '/',
'authenticity_token' => $authenticity_token
) );
你在这一行也犯了同样的错误:
CURLOPT_POSTFIELDS => 'screen_name=' . $username,
这一行一定是错误添加的:
CURLOPT_HTTPHEADER => [
"Content-type:text/html;charset=utf-8",
],
它是一个GET请求,没有请求主体,因此没有内容类型
,因为没有内容,所以不可能有内容类型头声明,请去掉它
这条线
CURLOPT_ENCODING => "gzip"
如果curl不是用gzip编译的,并且服务器实际决定使用gzip(更具体地说,您将获得无法理解的二进制数据),并且您没有提供任何代码来实际处理gzip二进制数据,那么将中断您的代码。一种更为稳健的方法是将其设置为emptystring“”
,然后curl将提供libcurl编译的所有编码,并将动态地为您对其进行反编码(包括gzip,如果在中编译的话)。它通常是gzip
和deflate
,但它也是未来的证明,因为它将自动添加任何未来的编码)
这条线
"Content-type: application/x-www-form-urlencoded",
不要自动添加此标题。libcurl将自动检测application/x-www-urlencode