Отключение логирования в Windows Azure

Есть такая проблема, как слишком много логов. Они по умолчанию включены в Azure и пишутся на диагностический диск. Если у вас роль маленькая, то диск этот размером в 15ГБ (+5ГБ сама система). К слову, есть такая фишка, что если заводить Extra Small Virtual Machine, а не Extra Small Web Role, то можно получить за теже 600 р в месяц диск на 120ГБ. Микрософт такое несоответствие объясняет тем, что на виртуальные машины обычно доставляют большие программы, вот и выделили места как у Small Instance.

Так вот, эти 15ГБ быстро исчерпываются, если у вас много обращений и автоматически не чистятся. Такое приводит к тому, что у роли вызывается процесс Reimage, что дает заметный перебой в работе. Чтобы в автоматическом деплое отключить логирование (конечно же для VM можно соединится по RDP и ручками настроить IIS как надо), достаточно подсоединить к проекту библиотеку Microsoft.Web.Administration, которая находится по пути C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll. А в фенкции старта самой роли прописать следующее:

Copy Source | Copy HTML
  1. var iisManager = new ServerManager();
  2. Configuration config = iisManager.GetApplicationHostConfiguration();
  3. ConfigurationSection httpLoggingSection = config.GetSection("system.webServer/httpLogging");
  4. httpLoggingSection["selectiveLogging"] = @"LogAll";
  5. httpLoggingSection["dontLog"] = true;
  6. iisManager.CommitChanges();

Метки:   Категории:Csharp | microsoft | Code


Немного про UTF-16 и отличие от UTF-8

Как мы знаем, все строчки в коде msvs обрабатываются как utf-16, хотя формально мы их называем как utf-8. Отличие заключается в нижних и верхних суррогатах, которые не понятно вообще зачем нужны. Проблема может возникнуть при индексировании разных текстов, когда идет вызов WCF сервиса и ему в параметре передается UTF-16 строчка, а сам сервис должен передавать в utf-8, поэтому найдя символ из utf-16 все успешно проваливается с сообщением - Unable to translate Unicode character \uDE09 at index 0 to specified code page. Один из сложных и рекомендуемых способов - переопределить кодировщик у WCF сервиса, однако можно и ручками предварительно перекодировать строчку, чтобы быть уверенным, что она содержит только utf-8 коды.
Copy Source | Copy HTML
  1. private static readonly Encoding Utf8Encoder = Encoding.GetEncoding(
  2.                 "UTF-8",
  3.                 new EncoderReplacementFallback(string.Empty),
  4.                 new DecoderExceptionFallback()
  5. );
  6. text = Utf8Encoder.GetString(Utf8Encoder.GetBytes(text""));

Метки:   Категории:Code


Библиотека для работы с SAPE и хранением данных в Azure Table Storage

По ссылке можно скачать проект библиотеки (исходники и бинарники) для биржи sape.ru . Хранение ссылок производиться в облачном BlogStorage, чтобы позволяет использовать библиотеку на любом проекте ASP.NET, в том числе и с несколькими WebRole's. Ключ доступа к таблице хранения задается в "Diagnostics.ConnectionString". Далее в конфиг прописываем секцию:
Copy Source | Copy HTML
  1. <configSections>
  2. <sectionGroup name="Sape">
  3.       <section name="SapeConfig" type="Sape.SapeConfigSection, SAPE" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
  4.     </sectionGroup>
  5.   </configSections>
  6. <Sape>
  7.     <SapeConfig UserId="111111111121a924a9cd073ff1d2b0da">
  8.       <DefaultDocuments>
  9.         <add Name="Default.aspx" />
  10.       </DefaultDocuments>
  11.     </SapeConfig>
  12.   </Sape>
И далее можем вставлять в любое место проекта ссылки сапы. Работает, как можно видеть только для ссылок, без контекстных ссылок:
Copy Source | Copy HTML
  1. <pages enableSessionState="false" enableViewStateMac="false" enableEventValidation="true" controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
  2.       <controls>
  3.         <add tagPrefix="efe" namespace="Sape" assembly="SAPE" />
  4.       </controls>
  5. </pages>
  6. <efe:SapeLinks runat="server"/>

Метки:   Категории:Code


Designing for Scale with Windows Azure Storage

Новый выпуск channel 9 рассказывающий про Azure Storage Tables. Это очень популярная тема, так как StorageTables скоро полностью вытеснят Azure SQL и уже поддерживают до 5000 операций в секунду из коробки. При этом, если почитать резюме ведущих разработчиков социальных сетей они гордятся какими-то 2000 операциями в секунду.
В самой телепередачи рассказано мало интересного, говорится банальное, что Ключевые поля должны быть селективными или селективными должны быть ключевые поля. Однако показана Tables Matrics Analitics , почему-то в описании не дана ссылка, которую может настроить себе любой, кто хочет отслеживать эффективность работы обращений в Azure Storage. Про аналитические возможности они заговорили, так как нет гарантий, что обращение к таблице будет обработано быстро. Иногда это может занимать секунды, поэтому пример показанный индусом про работы с миллиардами документов - в корне неправилен. Для большого объема запросов , также как и для блогов, часть документов должна подгружаться в оперативную память, для этого есть объектная модель, а обращения к таблицам или, что более привычно к SQL, должно делаться разово при инициализации. Соответственно при обращении к веб-роли, мы проверяем, что у нас в пямяти актуальные данные, что их не надо обновлять и быстренько возвращаем их пользователю. Если же пользователь делает какое-то действо, то нужно синхронизировать все инстансы через Azure Tables путем фонового обращения к таблицам. Именно фоновое, так как опять же нет никаких гарантий, что оно обработается быстро. Так например, чтобы не задерживать выдачу страницы из оперативной памяти, работа в Azure Tables в blogscloud реализована примерно таким кодом сощданием отдельного потока. Описание прокси класса SyncTimes публиковалось ранее.

Copy Source | Copy HTML
  1. Saved += (sender, args) =>
  2. {
  3.     Guid blogId = Blog.CurrentInstance.Id;
  4.     ThreadPool.QueueUserWorkItem(delegate
  5.     {
  6.         // because HttpContext is not available within this BG thread
  7.         // needed to determine the current blog instance,
  8.         // set override value here.
  9.         Blog.InstanceIdOverride = blogId;
  10.         foreach (SyncTime tableClass in SyncTimes<SyncTime>.CurrentInstance.GetAllInstances(Blog.CurrentInstance.Id.ToString()))
  11.         {
  12.             tableClass.UpdatePosts = DateTime.Now;
  13.             tableClass.UpdateDeletedPosts = DateTime.Now;
  14.             SyncTimes<SyncTime>.CurrentInstance.Update(tableClass, false);
  15.         }
  16.         SyncTimes<SyncTime>.CurrentInstance.Update(null);
  17.     });
  18. };

Метки: ,   Категории:Code


Использование Azure CDN для динамических страниц

Как мы знаем, микрософт предлагает невероятные возможности по распространению контента во все точки мира, что заметно уменьшает время доступа к контенту. Это CDN. Как я писал ранее это сокращает трафик между континентами (бэкбонами). Но, чтобы включить CDN у простого сайта есть несколько особенностей, о которых напишу под катом, так как не достаточно просто включить CDN в панели управления и настроить CNAME домена.
1) Надо понимать, что если мы выставили context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(10));//10min и сделали запрос через CDN, то результат этого запроса изменится не ранее чем через 10 минут.
2) В проекте создаем папку /cdn/ и настраиваем модуль rewrite для простой переброски всех запросов приходящих запросов следующим образом:
Copy Source | Copy HTML
  1. <system.webServer>
  2.   <rewrite>
  3.       <rules>
  4.         <rule name="0" stopProcessing="false">
  5.           <match url="^(?:cdn/)(.*)$"/>
  6.           <action type="Rewrite" url="{R:1}" appendQueryString="true"/>
  7.         </rule>
  8.     </rewrite>
  9.   </system.webServer>

3) Далее мы хотим, чтобы все наши ответы передавались в сжатом виде при помощи GZIP. Напомню, что GZIP отличается от deflate тем, что у последнего отсутствует избыточных заголовок. Итак, добавляем в проект модуль сжатия и настраиваем сжатие CompressionModule:
Copy Source | Copy HTML
  1. namespace Modules
  2. {
  3.     using System;
  4.     using System.IO;
  5.     using System.IO.Compression;
  6.     using System.Text;
  7.     using System.Text.RegularExpressions;
  8.     using System.Web;
  9.     using System.Web.UI;
  10.     using System.Net;
  11.     using System.Net.Sockets;
  12.     /// <summary>
  13.     /// Compresses the output using standard gzip/deflate.
  14.     /// </summary>
  15.     public sealed class CompressionModule : IHttpModule
  16.     {
  17.         #region Constants and Fields
  18.         /// <summary>
  19.         /// The deflate string.
  20.         /// </summary>
  21.         private const string Deflate = "deflate";
  22.         /// <summary>
  23.         /// The gzip string.
  24.         /// </summary>
  25.         private const string Gzip = "gzip";
  26.         #endregion
  27.         #region Public Methods
  28.         /// <summary>
  29.         /// Compresses the response stream using either deflate or gzip depending on the client.
  30.         /// </summary>
  31.         /// <param name="context">
  32.         /// The HTTP context to compress.
  33.         /// </param>
  34.         public static void CompressResponse(HttpContext context)
  35.         {
  36.             //Делаем так как у нас проксирование через CDN
  37.             context.Response.Cache.SetCacheability(HttpCacheability.Public);
  38.             context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(10));//10min
  39.             System.Diagnostics.Debug.WriteLine("compressing --->" + context.Request.Path);
  40.             if (IsEncodingAccepted(Deflate))
  41.             {
  42.                 context.Response.Filter = new DeflateStream(context.Response.Filter, CompressionMode.Compress);
  43.                 WillCompressResponse = true;
  44.                 SetEncoding(Deflate);
  45.             }
  46.             else if (IsEncodingAccepted(Gzip))
  47.             {
  48.                 context.Response.Filter = new GZipStream(context.Response.Filter, CompressionMode.Compress);
  49.                 WillCompressResponse = true;
  50.                 SetEncoding(Gzip);
  51.             }
  52.         }
  53.         #endregion
  54.         #region Private Methods
  55.         private static bool WillCompressResponse
  56.         {
  57.             get
  58.             {
  59.                 HttpContext context = HttpContext.Current;
  60.                 if (context == null) { return false; }
  61.                 return context.Items["will-compress-resource"] != null && (bool)context.Items["will-compress-resource"];
  62.             }
  63.             set
  64.             {
  65.                 HttpContext context = HttpContext.Current;
  66.                 if (context == null) { return; }
  67.                 context.Items["will-compress-resource"] = value;
  68.             }
  69.         }
  70.         #endregion
  71.         #region Implemented Interfaces
  72.         #region IHttpModule
  73.         /// <summary>
  74.         /// Disposes of the resources (other than memory) used by the module 
  75.         ///     that implements <see cref="T:System.Web.IHttpModule"></see>.
  76.         /// </summary>
  77.         void IHttpModule.Dispose()
  78.         {
  79.             // Nothing to dispose; 
  80.         }
  81.         /// <summary>
  82.         /// Initializes a module and prepares it to handle requests.
  83.         /// </summary>
  84.         /// <param name="context">
  85.         /// An <see cref="T:System.Web.HttpApplication"></see> 
  86.         ///     that provides access to the methods, properties, and events common to 
  87.         ///     all application objects within an ASP.NET application.
  88.         /// </param>
  89.         void IHttpModule.Init(HttpApplication context)
  90.         {
  91.             context.PreRequestHandlerExecute += ContextPostReleaseRequestState;
  92.             context.Error += new EventHandler(context_Error);
  93.         }
  94.         void context_Error(object sender, EventArgs e)
  95.         {
  96.             HttpContext context = ((HttpApplication)sender).Context;
  97.             Exception ex = context.Server.GetLastError();
  98.             // If this CompressionModule will be compressing the response and an unhandled exception
  99.             // has occurred, remove the WebResourceFilter as that will cause garbage characters to
  100.             // be sent to the browser instead of a yellow screen of death.
  101.             if (WillCompressResponse)
  102.             {
  103.                 context.Response.Filter = null;
  104.                 WillCompressResponse = false;
  105.             }
  106.         }
  107.         #endregion
  108.         #endregion
  109.         #region Methods
  110.         /// <summary>
  111.         /// Checks the request headers to see if the specified
  112.         ///     encoding is accepted by the client.
  113.         /// </summary>
  114.         /// <param name="encoding">
  115.         /// The encoding.
  116.         /// </param>
  117.         /// <returns>
  118.         /// The is encoding accepted.
  119.         /// </returns>
  120.         private static bool IsEncodingAccepted(string encoding)
  121.         {
  122.             var context = HttpContext.Current;
  123.             return context.Request.Headers["Accept-encoding"] != null &&
  124.                    context.Request.Headers["Accept-encoding"].Contains(encoding);
  125.         }
  126.         /// <summary>
  127.         /// Adds the specified encoding to the response headers.
  128.         /// </summary>
  129.         /// <param name="encoding">The encoding.</param>
  130.         private static void SetEncoding(string encoding)
  131.         {
  132.             HttpContext.Current.Response.AppendHeader("Content-encoding", encoding);
  133.         }
  134.         /// <summary>
  135.         /// Handles the BeginRequest event of the context control.
  136.         /// </summary>
  137.         /// <param name="sender">
  138.         /// The source of the event.
  139.         /// </param>
  140.         /// <param name="e">
  141.         /// The <see cref="System.EventArgs"/> instance containing the event data.
  142.         /// </param>
  143.         private static void ContextPostReleaseRequestState(object sender, EventArgs e)
  144.         {
  145.             var context = ((HttpApplication)sender).Context;
  146.             System.Diagnostics.Debug.WriteLine("precessing request --->" + context.Request.Path);
  147.             // only when page is requested 
  148.             if (context.CurrentHandler is Page &&
  149.                 context.Request["_TSM_HiddenField_"] == null &&
  150.                 context.Request["HTTP_X_MICROSOFTAJAX"] == null &&
  151.                 context.Request.HttpMethod == "GET")
  152.             {
  153.                 CompressResponse(context);
  154.             }
  155.         }
  156.         #endregion
  157.     }
  158. }

Copy Source | Copy HTML
  1.   <system.webServer>
  2.     <validation validateIntegratedModeConfiguration="false"/>
  3.     <staticContent>
  4.       <remove fileExtension=".js" />
  5.       <mimeMap fileExtension=".js" mimeType="text/javascript" />
  6.       <remove fileExtension=".css" />
  7.       <mimeMap fileExtension=".css" mimeType="text/css" />
  8.       <remove fileExtension=".ico"/>
  9.       <mimeMap fileExtension=".ico" mimeType="image/x-icon"/>
  10.       <remove fileExtension=".gif"/>
  11.       <mimeMap fileExtension=".gif" mimeType="image/gif"/>
  12.       <remove fileExtension=".woff"/>
  13.       <mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
  14.       <remove fileExtension=".svg"/>
  15.       <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
  16.       <clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
  17.     </staticContent>
  18.     <httpCompression
  19.         directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files"
  20.         cacheControlHeader="max-age=86400"
  21.         noCompressionForHttp10="false"
  22.         noCompressionForProxies="false"
  23.         noCompressionForRange="false"
  24.         sendCacheHeaders="true" minFileSizeForComp="0">
  25.       <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
  26.       <dynamicTypes>
  27.         <add mimeType="text/*" enabled="true" />
  28.         <add mimeType="message/*" enabled="true" />
  29.         <add mimeType="application/x-javascript" enabled="true" />
  30.         <add mimeType="*/*" enabled="false" />
  31.       </dynamicTypes>
  32.       <staticTypes>
  33.         <add mimeType="text/*" enabled="true" />
  34.         <add mimeType="message/*" enabled="true" />
  35.         <add mimeType="application/javascript" enabled="true" />
  36.         <add mimeType="*/*" enabled="false" />
  37.       </staticTypes>
  38.     </httpCompression>
  39.     <urlCompression doStaticCompression="true" doDynamicCompression="true" />
  40.     <modules runAllManagedModulesForAllRequests="true">
  41.       <add name="CompressionModule" type="Modules.CompressionModule"/>
  42.     </modules>
  43. </system.webServer>

4) Сразу особенность в том, что в CompressionModule мы не включаем сжатие для context.Request["_TSM_HiddenField_"] == null && context.Request["HTTP_X_MICROSOFTAJAX"] - это Ajax скрипты для AjaxControlToolkit и прочего от микрософта.
5) И в завершение нам необходимо сделать перезапись поля action у aspForm, так как при олучении обращения через CDN оно будет сформировано как "/cdn/page.aspx" , что при выполнении PostBack будет ошибка. Перезаписать action можно с помощью RewriteFormHtmlTextWriter, который вставляется в masterpage как
Copy Source | Copy HTML
  1. protected override void Render(HtmlTextWriter writer)
  2. {
  3.     base.Render(new RewriteFormHtmlTextWriter(writer));
  4. }
Copy Source | Copy HTML
  1. namespace top30{
  2.     using System.IO;
  3.     using System.Web;
  4.     using System.Web.UI;
  5.     /// <summary>
  6.     /// The RewriteFormHtmlTextWriter class implements Form action tag rewriting for rewritten pages 
  7.     ///     on Mono.
  8.     /// </summary>
  9.     public class RewriteFormHtmlTextWriter : HtmlTextWriter
  10.     {
  11.         #region Constructors and Destructors
  12.         /// <summary>
  13.         /// Initializes a new instance of the <see cref="RewriteFormHtmlTextWriter"/> class.
  14.         /// </summary>
  15.         /// <param name="writer">
  16.         /// The writer.
  17.         /// </param>
  18.         public RewriteFormHtmlTextWriter(Html32TextWriter writer)
  19.             : base(writer)
  20.         {
  21.             this.InnerWriter = writer.InnerWriter;
  22.         }
  23.         /// <summary>
  24.         /// Initializes a new instance of the <see cref="RewriteFormHtmlTextWriter"/> class.
  25.         /// </summary>
  26.         /// <param name="writer">
  27.         /// The writer.
  28.         /// </param>
  29.         public RewriteFormHtmlTextWriter(TextWriter writer)
  30.             : base(writer)
  31.         {
  32.             this.InnerWriter = writer;
  33.         }
  34.         #endregion
  35.         #region Public Methods
  36.         /// <summary>
  37.         /// Writes the specified markup attribute and value to the output stream, and, if specified, writes the value encoded.
  38.         /// </summary>
  39.         /// <param name="name">
  40.         /// The markup attribute to write to the output stream.
  41.         /// </param>
  42.         /// <param name="value">
  43.         /// The value assigned to the attribute.
  44.         /// </param>
  45.         /// <param name="encode">
  46.         /// true to encode the attribute and its assigned value; otherwise, false.
  47.         /// </param>
  48.         public override void WriteAttribute(string name, string value, bool encode)
  49.         {
  50.                 if (name == "action")
  51.                 {
  52.                     if (HttpContext.Current.Items["ActionAlreadyWritten"] == null)
  53.                     {
  54.                         value = HttpContext.Current.Request.RawUrl.Replace("/cdn/","/");
  55.                         HttpContext.Current.Items["ActionAlreadyWritten"] = true;
  56.                     }
  57.                 }
  58.             base.WriteAttribute(name, value, encode);
  59.         }
  60.         #endregion
  61.     }
  62. }

Метки:   Категории:microsoft | Code


Gamification of Coding

Микрософт создало плагин для Visial Studio с системой ачивментов. Написал прогу - 1 очко, написал работающую прогу - 2 очка, написал прогу работающую на новых технологиях - 5 очков . С первой компиляцией получилось 67 поинтов.

Метки:   Категории:Code


csharp xml skip serialization for int field

При использовании XML сериализации удобно, чтобы в результат не попадали поля, которые содержат нулевые значения. Для стринговых и объектных полей все просто, достаточно в классе создать свойство, которое на get делает проверку значения объекта и если не нужно включать его в XML, то возвращаем null. В случае простого поля типа INT ( decimal) не удобно переходить от простого int к System.Nulable (int?). Но на помощь приходит весьма интересный патерн, о котором вероятно многие и не знали. Достаточно завести в классе свойство public bool ShouldSerialize{FieldName}() {return {FieldName}.HasValue;} , которое указывает, нужно ли сериализовать переменную {FieldName} или нет.

Метки:   Категории:Code


TechDays 2012 Netherlands

Презентация о нововведениях в asp4.5 и msvs2011 с последней конференции в Нидерландах.

Метки:   Категории:Code


Manual DNS Azure Solution with Power Shell

О проблеме настройки DNS для Windows Azure уже упоминалось, но оказалось все сложнее. Российский регистратор webnames не смог выставить DNS для доменов на нужные, ссылаясь на ошибки в SOA записях, даже техподдержка пока не помогла. Так что домены по 90р за штуку до добра не доведут. Поэтому я озадачился поднятием и настройкой своего пула DNS серверов и видимо с этим столкнется любой разработчик, который захочет работать с Windows Azure без использования CDN (Content Delivery Network).

Алгоритм настройки получился следующим:
1) Заказываем на windows хостинге, например Агаве, пару VPS серверов IIS Web за 500р в месяц, включаем на каждом из них DNS Server, на втором настраиваем репликацию первого.Заводим нужные dns-зоны. Записи A указывающую на IP адрес myserver.cloudapp.net и CNAME на сайт и приставкой www. Также настраиваем SOA, чтобы TTL был секунд 20, а не час, для более быстрого обновления.
2) На primary DNS сервере ставим PowerShell из стандартного пакета. Для этого открываем раздел Features в списке возможных установок на сервер. Далее пишем Windows Service который бы раз в 5 минут опрашивает ваши сайты на предмет не изменился ли у них IP адрес. Если изменился, то выполняем определенный PowerShell-скрипт, код которого приведен ниже.
3) Первый PS-скрипт вызывается, когда служба только запускается и ей нужно определить список всех доменных зон на сервере, делается это так:
Copy Source | Copy HTML
  1. Get-WmiObject -ComputerName localhost -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_AType |Sort-Object -unique containername|Select containername,ipaddress

4) И второй PS-скрипт, когда обнаружены домены, для которых нужно поменять А записи, вызывается такой вот скрипт. Вызов выглядит как "./update-DNSAddress -forward localhost -reverse localhost". Где в файле dnsaddresslist.csv со списком нужных изменений IP адресов присутствует шапка "Name,Address" и далее по паре домен-айпи на каждой строчке разделенных запятой.

Это базовые знания, чтобы решить проблемы динамических адресов в Azure, но при желании могу добавить ваш домен на свои обновляемые DNS server'a.

bonus: Пример Csharp функции по запуску PowerShell скрипта, сохраненного на диск файлом, с параметром и получением результата работы скрипта.

Метки: ,   Категории:microsoft | Code


Рейтинг блогосферы - пост 4 (про ссылки)

Примечательно, что с каким бы программистом я не начинал обсуждать алгоритм составления ТОПа, в итоге каждый говорил, что вот он сейчас пойдет создаст сайт, выложит там новый ТОП и станет популярным. Это с одной стороны хорошо, так как показывает, что программисты - люди дела и любители играть в разные алгоритмы, а также мечтают стать знаменитыми. Но с другой стороны показывает, что они не понимают
1) Как работать в команде,
2) Что так как все работают с одним векторным пространством и одинаковыми сырыми данными, то в итоге рейтинг у всех будет совпадать в значительной степени.(~20%)
3) Самая сложность не в первоначальной сортировке, а в последующих фильтрах, которые должны отсеять спамерские посты. А спамерские посты чаще всего имеют ссылки как входящие, на сам пост, так и исходящие - на рекламу - которые нужно уметь определять и фильтровать. Вот об этом алгоритме работы нового ТОПа и поговорим.

После 4х летнего изучения топов я с полной уверенностью могу сказать, что нет смысла составлять списки бана, то есть лишать определенныз определенных блогеров шанса попасть в ТОП. Ибо это равносильно тому, чтобы посадить своего модератора, так как спамер может создавать новые блоги каждый день. В связи с этим логичным видится
1) фильтр по ссылкам, которые содержаться в посте - то есть все ссылки должны проходить проверку через сервис opendns, чтобы исключить ссылки на фишинговые сайты в топе или на сайты с вирусами. Минус - медленная работа по отбору записей, поэтому я пока ограничился самосоставленным списком с плохими ресурсами. И если в после есть ссылка на плохой ресурс, то пост не попадет в топ. Также я расматриваю вариант, когда на наличие плохих ссылок будет анализироваться вся главная страница блога и страница профиля, так как вероятно их откроет человек захотевший узнать побольше об авторе ТОПа и этим тоже пользуются спамеры.
2) ссылки на популярные сервисы сокращения ссылок (bit.ly) можно пока не фильтровать, так как эти сервисы сами заинтересованы в фильтрации ссылок на фишинговые и вирусные сайты.
3) Ранее я упомянул фильтр на локальный экстримум - он заключается в том, что проверяется, что за локальный период времени ссылок именно на этот пост блогера было больше всего или комментариев было больше всего. Это прежде всего позволяет отфильтровать тех у кого есть трансляции и у кого стабильно по несколько ссылок между своими трансляциями. Также отфильтрует тех, у кого стабильно много комментариев, например из-за спама в комментариях.
4) Анализируя спамерскую активность я пришел к выводу в необходимости фильтра "LinksIntegrity" - задача которого проверить все ссылки на расматриваемый пост, отбросить одинаковые, отбросить те, которые сделаны из сообществ и отбросить все ссылки с микроблогов. Повышенная активность в микроблогах и то, что там почти каждый пост содержит ссылки - говорит о том, что нельзя микроблоги причислять к полноценным блогам. Кроме того в микроблогах сейчас каждый упоминание типа "@user" - считается ссылкой и это сильно перекосило рейтинг блогеров и вызывает недоумение в определенных кругах. Итак, после отбора ссылок, проверяется, что оставшееся число ссылок достаточно для того, чтобы интегральная характеристика поста оставалась среди 20% постов с наибольшим значением.


Метки:   Категории:Blogs | Analytics | topbot | Code


Кто я?

Программист. Я слежу за блогосферой и знаю, как будет развиваться интернет. Когда у меня есть время я даже прилагаю для этого усилия. Подробнее

Последние комментарии

Не отображать

Topbot at FeedsBurner

Мои Твиты

Twitter июня 22, 12:28
Суперлайки в Перископе http://dlvr.it/PPDsML

Twitter июня 21, 21:13
Что такое любовь? Песнь льда и пламени http://dlvr.it/PP4nxv https://twitter.com/f1ashr/status/877635527108722689/photo/1

Twitter июня 21, 09:57
Найдено применение для дополненной реальности http://dlvr.it/PNxLxw https://twitter.com/f1ashr/status/877465389294247936/photo/1

Twitter июня 21, 01:59
Periscope VIP что это? http://dlvr.it/PNsDcb https://twitter.com/f1ashr/status/877345106982035457/photo/1

Twitter июня 20, 22:13
Итоги 2016 года в Живом Журнале http://dlvr.it/PNqHw1 https://twitter.com/f1ashr/status/877288232597168128/photo/1

Twitter июня 20, 20:36
Гравитация. Сила тяжести. (Теория общего знания, часть 17) http://dlvr.it/PNpKGs https://twitter.com/f1ashr/status/877263840982913025/photo/1

Twitter июня 20, 20:36
Идеальное решение для Курильских островов http://dlvr.it/PNpKHy

Twitter июня 20, 20:36
Изменения в API Facebook / Youtube / Instagram http://dlvr.it/PNpKD4 https://twitter.com/f1ashr/status/877263832963399680/photo/1

Twitter июня 20, 20:36
Неинформативное бесполезное содержание от Google http://dlvr.it/PNpK5L https://twitter.com/f1ashr/status/877263822372847616/photo/1

Twitter июня 19, 18:29
Правила обрезания плодовых деревьев http://dlvr.it/PNVtKx https://twitter.com/f1ashr/status/876869473524789248/photo/1

Twitter июня 19, 11:51
Мобильное приложение t30p убрано из AppStore http://dlvr.it/PNQKMg

Twitter июня 9, 09:56
CDN for HTTPS на Azure http://dlvr.it/PKyPl4

Twitter июня 8, 09:12
Поиск причины популярности спиннеров http://dlvr.it/PKgm7x https://twitter.com/f1ashr/status/872743030532354048/photo/1

Twitter июня 7, 09:36
Beep-Beep Im a Sheep (go crazy now) http://dlvr.it/PKPk5M https://twitter.com/f1ashr/status/872386692468101120/photo/1

Twitter июня 7, 07:37
Где россияне праздновали новый 2017 год http://dlvr.it/PKNbfk https://twitter.com/f1ashr/status/872356936511098885/photo/1

Twitter июня 7, 04:59
7 лет аккаунту в твиттере http://dlvr.it/PKMDFt

Twitter июня 7, 01:49
Теневой бизнес ГИБДД http://dlvr.it/PKKlKx https://twitter.com/f1ashr/status/872269148281159680/photo/1

Twitter июня 6, 18:19
Трансляции Одноклассников (http://Ok.ru/live) добавлены в t30p http://dlvr.it/PKFBJH https://twitter.com/f1ashr/status/872156036446027776/photo/1

Twitter июня 6, 17:15
О смене дизайна Вконтакте http://dlvr.it/PKDQb5

Twitter июня 6, 17:15
Непонятные конкурсы в Твиттере http://dlvr.it/PKDQNz https://twitter.com/f1ashr/status/872139813071101952/photo/1

Мой твиттер

Копирайт

Все мысли, высказанные в блоге, являются моим мнением и за это мнение меня никто не забанит! Кроме того, никто не имеет право копировать материалы блога без использования ctrl+C/V!

© Copyright 2008