好的,所以我认为这可能是(需要一些改动)你需要什么。
注意事项:
- 这是PHP,不C#(可是你说你感兴趣的任何服务器端语言)。
- 此代码会嵌入(非官方)Pinterest搜索终结点。您需要更改$ data和$ search_res以反映您的任务的适当端点(例如BoardFeedResouce)。注意:至少在搜索时,Pinterest目前使用两个端点,一个用于初始页面加载,另一个用于无限滚动操作。每个都有自己的预期参数结构。
- Pinterest没有官方的公开API,只要他们改变任何内容,并且没有任何警告,就会期望它被破坏。
- 你可能会发现pinterestapi.co.uk更容易实施和接受你正在做的事情。
- 我有一些演示/调试代码下的类不应该在那里,一旦你得到你想要的数据,并且你可能想改变一个默认的页面提取限制。
问题的兴趣:
- 下划线
_
参数需要在JavaScript格式,即时间戳。比如Unix时间,但是它增加了毫秒。它实际上并未用于分页。
- 分页使用
bookmarks
属性,因此您向不需要它的“新”端点发出第一个请求,然后从结果中取出bookmarks
,并在请求中使用它以获取下一个“页面”结果,然后从这些结果中取出bookmarks
以获取下一页,等等,直到用完结果或达到预设的限制(或者在脚本执行时间点击服务器最大值)。我很想知道bookmarks
字段的编码。我想认为除了一个PIN码或其他页面标记之外,还有一些有趣的秘密酱油。
- 我跳过html,而是处理JSON,因为比使用DOM操作解决方案或一堆正则表达式更容易(对我来说)。
<?php
if(!class_exists('Skrivener_Pins')) {
class Skrivener_Pins {
/**
* Constructor
*/
public function __construct() {
}
/**
* Pinterest search function. Uses Pinterest's "internal" page APIs, so likely to break if they change.
* @author [@skrivener] Philip Tillsley
* @param $search_str The string used to search for matching pins.
* @param $limit Max number of pages to get, defaults to 2 to avoid excessively large queries. Use care when passing in a value.
* @param $bookmarks_str Used internally for recursive fetches.
* @param $pages Used internally to limit recursion.
* @return array() int['id'], obj['image'], str['pin_link'], str['orig_link'], bool['video_flag']
*
* TODO:
*
*
*/
public function get_tagged_pins($search_str, $limit = 1, $bookmarks_str = null, $page = 1) {
// limit depth of recursion, ie. number of pages of 25 returned, otherwise we can hang on huge queries
if($page > $limit) return false;
// are we getting a next page of pins or not
$next_page = false;
if(isset($bookmarks_str)) $next_page = true;
// build url components
if(!$next_page) {
// 1st time
$search_res = 'BaseSearchResource'; // end point
$path = '&module_path=' . urlencode('SearchInfoBar(query=' . $search_str . ', scope=boards)');
$data = preg_replace("'[\n\r\s\t]'","",'{
"options":{
"scope":"pins",
"show_scope_selector":true,
"query":"' . $search_str . '"
},
"context":{
"app_version":"2f83a7e"
},
"module":{
"name":"SearchPage",
"options":{
"scope":"pins",
"query":"' . $search_str . '"
}
},
"append":false,
"error_strategy":0
}');
} else {
// this is a fetch for 'scrolling', what changes is the bookmarks reference,
// so pass the previous bookmarks value to this function and it is included
// in query
$search_res = 'SearchResource'; // different end point from 1st time search
$path = '';
$data = preg_replace("'[\n\r\s\t]'","",'{
"options":{
"query":"' . $search_str . '",
"bookmarks":["' . $bookmarks_str . '"],
"show_scope_selector":null,
"scope":"pins"
},
"context":{
"app_version":"2f83a7e"
},
"module":{
"name":"GridItems",
"options":{
"scrollable":true,
"show_grid_footer":true,
"centered":true,
"reflow_all":true,
"virtualize":true,
"item_options":{
"show_pinner":true,
"show_pinned_from":false,
"show_board":true
},
"layout":"variable_height"
}
},
"append":true,
"error_strategy":2
}');
}
$data = urlencode($data);
$timestamp = time() * 1000; // unix time but in JS format (ie. has ms vs normal server time in secs), * 1000 to add ms (ie. 0ms)
// build url
$url = 'http://pinterest.com/resource/' . $search_res . '/get/?source_url=/search/pins/?q=' . $search_str
. '&data=' . $data
. $path
. '&_=' . $timestamp;//'1378150472669';
// setup curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("X-Requested-With: XMLHttpRequest"));
// get result
$curl_result = curl_exec ($ch); // this echoes the output
$curl_result = json_decode($curl_result);
curl_close ($ch);
// clear html to make var_dumps easier to see when debugging
// $curl_result->module->html = '';
// isolate the pin data, different end points have different data structures
if(!$next_page) $pin_array = $curl_result->module->tree->children[1]->children[0]->children[0]->children;
else $pin_array = $curl_result->module->tree->children;
// map the pin data into desired format
$pin_data_array = array();
$bookmarks = null;
if(is_array($pin_array)) {
if(count($pin_array)) {
foreach ($pin_array as $pin) {
//setup data
$image_id = $pin->options->pin_id;
$image_data = (isset($pin->data->images->originals)) ? $pin->data->images->originals : $pin->data->images->orig;
$pin_url = 'http://pinterest.com/pin/' . $image_id . '/';
$original_url = $pin->data->link;
$video = $pin->data->is_video;
array_push($pin_data_array, array(
"id" => $image_id,
"image" => $image_data,
"pin_link" => $pin_url,
"orig_link" => $original_url,
"video_flag" => $video,
));
}
$bookmarks = reset($curl_result->module->tree->resource->options->bookmarks);
} else {
$pin_data_array = false;
}
}
// recurse until we're done
if(!($pin_data_array === false) && !is_null($bookmarks)) {
// more pins to get
$more_pins = $this->get_tagged_pins($search_str, $limit, $bookmarks, ++$page);
if(!($more_pins === false)) $pin_data_array = array_merge($pin_data_array, $more_pins);
return $pin_data_array;
}
// end of recursion
return false;
}
} // end class Skrivener_Pins
} // end if
/**
* Debug/Demo Code
* delete or comment this section for production
*/
// output headers to control how the content displays
// header("Content-Type: application/json");
header("Content-Type: text/plain");
// header("Content-Type: text/html");
// define search term
// $tag = "vader";
$tag = "haemolytic";
// $tag = "qjkjgjerbjjkrekhjk";
if(class_exists('Skrivener_Pins')) {
// instantiate the class
$pin_handler = new Skrivener_Pins();
// get pins, pinterest returns 25 per batch, function pages through this recursively, pass in limit to
// override default limit on number of pages to retrieve, avoid high limits (eg. limit of 20 * 25 pins/page = 500 pins to pull
// and 20 separate calls to Pinterest)
$pins1 = $pin_handler->get_tagged_pins($tag, 2);
// display the pins for demo purposes
echo '<h1>Images on Pinterest mentioning "' . $tag . '"</h1>' . "\n";
if($pins1 != false) {
echo '<p><em>' . count($pins1) . ' images found.</em></p>' . "\n";
skrivener_dump_images($pins1, 5);
} else {
echo '<p><em>No images found.</em></p>' . "\n";
}
}
// demo function, dumps images in array to html img tags, can pass limit to only display part of array
function skrivener_dump_images($pin_array, $limit = false) {
if(is_array($pin_array)) {
if($limit) $pin_array = array_slice($pin_array, -($limit));
foreach ($pin_array as $pin) {
echo '<img src="' . $pin['image']->url . '" width="' . $pin['image']->width . '" height="' . $pin['image']->height . '" >' . "\n";
}
}
}
?>
让我知道,如果你碰上得到这个适应您的具体端点的问题。对于代码中的任何不合适的Apols,它最初都没有生成。
它只加载25个,因为当您滚动到底部时,通过ajax加载其余的部分,即“无限滚动”。我想你必须模仿滚动。或者如果他们将手指拉出来,他们已经发布了他们的API。 – mattytommo
当AJAX事件被调用时,我无法管理到底发生了什么?这是一个真正的耻辱关于API –
嗯,我不这么认为。你可能会更好地尝试使用JavaScript/Jquery,这样你可以获得所有的链接,然后模仿滚动到最后,然后重复,直到滚动完成后,你可以发送一个字符串数组到服务器。 – mattytommo