使用C#格式化Twitter文本(TweetText)

12

有没有更好的方法将来自Twitter的文本格式化为超链接、用户名和标签?我已经实现了这个功能,但我知道这可以做得更好。我对替代技术很感兴趣。我正在将其设置为ASP.NET MVC的HTML Helper。

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;

namespace Acme.Mvc.Extensions
{

    public static class MvcExtensions
    {
        const string ScreenNamePattern = @"@([A-Za-z0-9\-_&;]+)";
        const string HashTagPattern = @"#([A-Za-z0-9\-_&;]+)";
        const string HyperLinkPattern = @"(http://\S+)\s?";

        public static string TweetText(this HtmlHelper helper, string text)
        {
            return FormatTweetText(text);
        }

        public static string FormatTweetText(string text)
        {
            string result = text;

            if (result.Contains("http://"))
            {
                var links = new List<string>();
                foreach (Match match in Regex.Matches(result, HyperLinkPattern))
                {
                    var url = match.Groups[1].Value;
                    if (!links.Contains(url))
                    {
                        links.Add(url);
                        result = result.Replace(url, String.Format("<a href=\"{0}\">{0}</a>", url));
                    }
                }
            }

            if (result.Contains("@"))
            {
                var names = new List<string>();
                foreach (Match match in Regex.Matches(result, ScreenNamePattern))
                {
                    var screenName = match.Groups[1].Value;
                    if (!names.Contains(screenName))
                    {
                        names.Add(screenName);
                        result = result.Replace("@" + screenName,
                           String.Format("<a href=\"http://twitter.com/{0}\">@{0}</a>", screenName));
                    }
                }
            }

            if (result.Contains("#"))
            {
                var names = new List<string>();
                foreach (Match match in Regex.Matches(result, HashTagPattern))
                {
                    var hashTag = match.Groups[1].Value;
                    if (!names.Contains(hashTag))
                    {
                        names.Add(hashTag);
                        result = result.Replace("#" + hashTag,
                           String.Format("<a href=\"http://twitter.com/search?q={0}\">#{1}</a>",
                           HttpUtility.UrlEncode("#" + hashTag), hashTag));
                    }
                }
            }

            return result;
        }

    }

}

常量字符串 HyperLinkPattern = @"(http(s)?://\S+)\s?"; // 同时支持 https - dotnet-provoke
3个回答

3

这与我编写的在我的博客上显示Twitter状态的代码非常相似。我所做的进一步操作是:

1)查找@name并将其替换为<a href="http://twitter.com/name">真实姓名</a>

2)连续多个@name如果没有逗号,则添加逗号;

3)以@name(们)开头的推文格式为“致@name:”。

我认为这是解析推文的有效方法——它们具有非常一致的格式(适用于正则表达式),在大多数情况下速度(毫秒级别)也是可以接受的。

编辑:

这是我的Tweet解析器的代码。 它有点长,无法放在Stack Overflow答案中。它可以将推文转换成以下格式:

@user1 @user2看看我从@user3获得的酷链接:http://url.com/page.htm#anchor #coollinks

并将其转换为:

<span class="salutation">
    To <a href="http://twitter.com/user1">Real Name</a>,
    <a href="http://twitter.com/user2">Real Name</a>:
</span> check out this cool link I got from
<span class="salutation">
    <a href="http://www.twitter.com/user3">Real Name</a>
</span>:
<a href="http://site.com/page.htm#anchor">http://site.com/...</a>
<a href="http://twitter.com/#search?q=%23coollinks">#coollinks</a>

它还会用一些JavaScript将所有标记包装起来:
document.getElementById('twitter').innerHTML = '{markup}';

这样做是为了使推特获取器可以作为JS异步运行,如果Twitter出现问题或变慢,它不会影响我的网站页面加载时间。

@Brennan,这里有一种更好的方法 - (?<!://[^\s]+)#[A-Za-z0-9]+ 可以匹配任何 # 后跟一个或多个字母数字字符,当它不是由 :// 和任何非空格字符前导时。这应该可以匹配所有的标签,但是在 URL 中的任何 # 都将失败。 - Rex M
@Chance请随意使用,如果您想给我信用,但并非必要。 - Rex M
@Rex 更通用的URI会更好:[A-Za-z0-9\-_]*:[^\w]* - 例如:call-to:foo。此外,您的代码容易受到XSS攻击;您应该对任何插入的文本(特别是href)进行HttpUtility.HtmlEncode()编码。 - Jonathan Dickinson
@Jonathan 技术上说是对的,但这并不是一个旨在提供防弹解决方案的意图。成本效益平衡使我倾向于相信来自Twitter的输入并仅支持URL。 - Rex M
3
链接失效了,有没有可能重新复制代码?可以用GIST或其他网站。 - Rippo
显示剩余5条评论

0

0
我创建了一个帮助方法,可以将文本缩短为140个字符,并包含URL。您可以将分享长度设置为0,以从推文中排除URL。
 public static string FormatTwitterText(this string text, string shareurl)
    {
        if (string.IsNullOrEmpty(text))
            return string.Empty;

        string finaltext = string.Empty;
        string sharepath = string.Format("http://url.com/{0}", shareurl);

        //list of all words, trimmed and new space removed
        List<string> textlist = text.Split(' ').Select(txt => Regex.Replace(txt, @"\n", "").Trim())
                              .Where(formatedtxt => !string.IsNullOrEmpty(formatedtxt))
                              .ToList();

        int extraChars = 3; //to account for the two dots ".."
        int finalLength = 140 - sharepath.Length - extraChars;
        int runningLengthCount = 0;
        int collectionCount = textlist.Count;
        int count = 0;
        foreach (string eachwordformated in textlist
                .Select(eachword => string.Format("{0} ", eachword)))
        {
            count++;
            int textlength = eachwordformated.Length;
            runningLengthCount += textlength;
            int nextcount = count + 1;

            var nextTextlength = nextcount < collectionCount ? 
                                             textlist[nextcount].Length : 
                                             0;

            if (runningLengthCount + nextTextlength < finalLength)
                finaltext += eachwordformated;
        }

        return runningLengthCount > finalLength ? finaltext.Trim() + ".." : finaltext.Trim();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接