我真的很困惑 Twitter 如何期望其 API 的用户将其发送的纯文本推文转换为正确链接的 HTML。
事情是这样的:当您请求推文的详细数据时,Twitter 的 JSON API 会发回这组信息:
{
"created_at":"Wed Jul 18 01:03:31 +0000 2012",
"id":225395341250412544,
"id_str":"225395341250412544",
"text":"This is a test tweet. #boring @nbc http://t.co/LUfDreY6 #skronk @crux http://t.co/VpuMlaDs @twitter",
"source":"web",
"truncated":false,
"in_reply_to_status_id":null,
"in_reply_to_status_id_str":null,
"in_reply_to_user_id":null,
"in_reply_to_user_id_str":null,
"in_reply_to_screen_name":null,
"user": <REDACTED>,
"geo":null,
"coordinates":null,
"place":null,
"contributors":null,
"retweet_count":0,
"entities":{
"hashtags":[
{
"text":"boring",
"indices":[22,29]
},
{
"text":"skronk",
"indices":[56,63]
}
],
"urls":[
{
"url":"http://t.co/LUfDreY6",
"expanded_url":"http://www.twitter.com",
"display_url":"twitter.com",
"indices":[35,55]
},
{
"url":"http://t.co/VpuMlaDs",
"expanded_url":"http://www.example.com",
"display_url":"example.com",
"indices":[70,90]
}
],
"user_mentions":[
{
"screen_name":"nbc",
"name":"NBC",
"id":26585095,
"id_str":"26585095",
"indices":[30,34]
},
{
"screen_name":"crux",
"name":"Z. D. Smith",
"id":407213,
"id_str":"407213",
"indices":[64,69]
},
{
"screen_name":"twitter",
"name":"Twitter",
"id":783214,
"id_str":"783214",
"indices":[91,99]
}
]
},
"favorited":false,
"retweeted":false,
"possibly_sensitive":false
}
对于这个问题,有趣的部分是 text
元素和 hashtags
、user_mentions
和 urls 中的条目
数组。 Twitter 告诉我们在 text
元素中 hastags、mentions 和 urls 出现在 indices
数组中的什么地方……所以这就是问题的症结所在:
您如何使用那些索引
数组?
您不能通过使用 substr_replace
之类的循环遍历每个链接元素来直接使用它们,因为替换 text
中的第一个链接元素将使后续链接元素的所有索引值无效。您也不能使用 substr_replace
的数组功能,因为它仅在您为第一个 arg 提供字符串数组而不是单个字符串时才起作用(我已经测试过这个。结果......很奇怪)。
是否有一些函数可以同时用不同的替换字符串替换单个字符串中多个索引分隔的子字符串?
最佳答案
要使用 twitter 直接提供的索引和一个简单的替换,您需要做的就是收集您想要进行的替换,然后将它们向后排序。您可能会找到一种更聪明的方法来构建 $entities,无论如何我都希望它们是可选的,所以我就亲吻它。
无论哪种方式,我在这里的观点只是为了表明您不需要展开字符串和字符数等等。不管你怎么做,你需要做的就是从末尾开始,一直到字符串的开头,twitter 的索引仍然有效。
<?php
function json_tweet_text_to_HTML($tweet, $links=true, $users=true, $hashtags=true)
{
$return = $tweet->text;
$entities = array();
if($links && is_array($tweet->entities->urls))
{
foreach($tweet->entities->urls as $e)
{
$temp["start"] = $e->indices[0];
$temp["end"] = $e->indices[1];
$temp["replacement"] = "<a href='".$e->expanded_url."' target='_blank'>".$e->display_url."</a>";
$entities[] = $temp;
}
}
if($users && is_array($tweet->entities->user_mentions))
{
foreach($tweet->entities->user_mentions as $e)
{
$temp["start"] = $e->indices[0];
$temp["end"] = $e->indices[1];
$temp["replacement"] = "<a href='https://twitter.com/".$e->screen_name."' target='_blank'>@".$e->screen_name."</a>";
$entities[] = $temp;
}
}
if($hashtags && is_array($tweet->entities->hashtags))
{
foreach($tweet->entities->hashtags as $e)
{
$temp["start"] = $e->indices[0];
$temp["end"] = $e->indices[1];
$temp["replacement"] = "<a href='https://twitter.com/hashtag/".$e->text."?src=hash' target='_blank'>#".$e->text."</a>";
$entities[] = $temp;
}
}
usort($entities, function($a,$b){return($b["start"]-$a["start"]);});
foreach($entities as $item)
{
$return = substr_replace($return, $item["replacement"], $item["start"], $item["end"] - $item["start"]);
}
return($return);
}
?>
关于PHP:如何使用 Twitter API 数据将推文中的 URL、提及和主题标签转换为链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11533214/