我一直在开发一个能够登录AWeber.com并执行大量数据导入的程序。该脚本使用PHP cURL库及其CookieJar设置来欺骗普通用户使用浏览器。
脚本运行良好,允许登录和更改列表,但是当发布表单数据时(在submitData函数中),脚本总是失败。每次网站将输出指示会话已过期的网页,并要求“用户”再次登录。该页面还要求“用户”在其浏览器中启用cookie。
我花了最后几天来诊断这个问题,这让我完全难过。 CURLOPT_VERBOSE设置表明cURL正在将cookie传递给网站,cookiejar文件包含cookie,并且已从原因因素中消除了其他因素,如Referer和Javascript要求。
我将不胜感激为什么会出现这种情况以及解决问题的方法。导致错误的类和代码显示如下。代码标记在发生错误的位置。
<?php
class AWeber {
private $cj;
public function __construct() {
$this->cj = tempnam('/tmp', 'mlcookies_');
}
private function postQuery( $url, $array ) {
$cu = curl_init();
curl_setopt( $cu, CURLOPT_URL, $url );
curl_setopt( $cu, CURLOPT_POST, true );
curl_setopt( $cu, CURLOPT_POSTFIELDS, $array );
curl_setopt( $cu, CURLOPT_COOKIEJAR, $this->cj );
curl_setopt( $cu, CURLOPT_COOKIEFILE, $this->cj );
curl_setopt( $cu, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $cu, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $cu, CURLOPT_HEADER, true );
curl_setopt( $cu, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)' );
$return = curl_exec($cu);
echo $return;
curl_close($cu);
return $return;
}
private function getQuery( $url ) {
$cu = curl_init();
curl_setopt( $cu, CURLOPT_COOKIEJAR, $this->cj );
curl_setopt( $cu, CURLOPT_COOKIEFILE, $this->cj );
curl_setopt( $cu, CURLOPT_URL, $url );
curl_setopt( $cu, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $cu, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $cu, CURLOPT_HEADER, true );
curl_setopt( $cu, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)' );
$return = curl_exec($cu);
curl_close($cu);
echo $return;
return $return;
}
public function login( $user, $pass ) {
$this->getQuery( "https://www.aweber.com/login.htm" ); // Get page cookie checks
$query = array(
'_method' => 'POST',
'data[Account][username]' => $user,
'data[Account][password]' => $pass,
'data[Account][remember_login]' => '1'
);
$return = $this->postQuery( "https://www.aweber.com/login.htm", $query );
$this->getQuery( "https://www.aweber.com/users/" );
if ( !$return ) return false;
if ( strpos($return, '<div class="aw-status-headline">Error</div>') === false ) {
return true;
} else {
return false;
}
}
public function setList( $list ) {
$return = $this->getQuery( "https://www.aweber.com/users/lists/change/" . $list );
if ( !$return ) return false;
if ( strpos($return, '<option selected="selected" id="listSelectionActiveOption" value="' . $list . '">' ) === false ) {
return false;
} else {
return true;
}
}
public function submitData( $text, $note ) {
$query = array(
'upload_file' => '1',
'data[ImportWizard][leads]' => $text,
'data[ImportWizard][delimiter]' => 'TAB',
'data[ImportWizard][customer_note]' => $note,
'data[ImportWizard][use_automation]' => '1',
'cmd' => 'Next',
);
$return = $this->postQuery( "https://www.aweber.com/users/lead_imports", $query );
echo $return;
if ( !$return || strpos($return, '<h1>Step 2</h1>') === false ) return false;
$query = array(
'columnArray' => '',
'columnArray' => '',
'data[ImportWizard][column0]' => 'name',
'data[ImportWizard][column1]' => 'email',
'cmd' => 'Save',
);
$return = $this->postQuery( "https://www.aweber.com/users/lead_imports", $query );
if ( !$return || strpos($return, '<div class="aw-status-headline">Import Queued</div>') === false ) return false;
return true;
}
}
$aw = new AWeber(); // Create new AWeber interface class instance
$aw->login( $aUser, $aPass ) or trigger_error('Login failed', E_USER_ERROR); // Login
$aw->setList( 'list1' ) or trigger_error('List change 1 failed', E_USER_ERROR); // Change mailing list to 'list1'
// *** CODE WILL FAIL HERE WITH "Data submit 1 failed" ERROR ***
$aw->submitData( "Test\tTesterrr\nTest2\tTesterrr2\nTest3\tTesterrr3\n", "Testing Testing Testing Testing Testing Testing Testing" ) or trigger_error('Data submit 1 failed', E_USER_ERROR); // Submit data
$aw->setList( 'list2' ) or trigger_error('List change 2 failed', E_USER_ERROR); // Change mailing list to 'list2'
?>
答案 0 :(得分:1)
这可能是因为您在会话期间在调用之间使用curl_close关闭curl句柄。它应该只在会话使用完成后关闭。
答案 1 :(得分:1)
我认为Turnkey是正确的。
可能是因为你正在关闭 使用curl_close进行卷曲处理 在会话期间的呼叫之间。它 应该只在关闭之后关闭 会话使用完成。
您不能打开两个不同的卷曲会话。 尝试在一个会话中执行所有操作,然后关闭会话。
尝试在类的析构函数中添加curl_close()。将curl会话存储在变量中。并使用$ this-&gt; curl_session访问它。 这是一个例子
<?php
class AWeber {
$curl_session;
$cj;
function __construct() {
$this->curl_session = curl_init();
}
function __destruct() {
if($this->curl_session) {
curl_close($this->curl_session);
}
}
function doWhatever() {
curl_setopt( $this->curl_session, CURLOPT_COOKIEJAR, $this->cj );
curl_setopt( $this->curl_session, CURLOPT_COOKIEFILE, $this->cj );
curl_setopt( $this->curl_session, CURLOPT_URL, $url );
curl_setopt( $this->curl_session, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $this->curl_session, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $this->curl_session, CURLOPT_HEADER, true );
curl_setopt( $this->curl_session, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)' );
$return = curl_exec($this->curl_session);
}
}
?>
答案 2 :(得分:0)
您可能需要读取从第一个查询发回的响应标头数据。然后将会话信息(JSSESSION / PHPSESSID / etc)作为cookie信息传回。
我认为您的发布数据脚本正在重置Cookie数据(不确定如何)。使用Firebug监视执行这些操作时发送和接收的标头。然后检查cookie文件以确保它们不被覆盖。
答案 3 :(得分:0)
您应该检查Cookie文件。如果一切正常,它应该有信息。如果没有,也许您应该使用cwd()
来指定绝对路径。
答案 4 :(得分:0)
将POST-Parameters指定为Array时,使用curl时遇到了一些问题。而不是
curl_setopt( $cu, CURLOPT_POSTFIELDS, $array );
我用:
curl_setopt( $cu, CURLOPT_POSTFIELDS, http_build_query($array) );
这对我有用。