Добрый день!
Хочу поделится методом интеграции альбомов Facebook в сайт.
Метод реализован на C# с использованием Linq, однако основная логика работы находится в регулярных выражениях и легко может быть воспроизведена на любом другом языке программирования.
Предыстория, или с чего все началось
А началось все с разработки ресурса для сообщества путешественников, любителей жизни, да и просто замечательных людей — ONE ☆ LIFE.
На момент начала разработки у сообщества было уже несколько тысяч фотографий в альбомах Facebook-группы. Поскольку дублировать все фотографии на сайт не рационально, а необходимость иллюстрировать события и публикации на сайте возникает достаточно часто — было решено сделать возможность импорта фотографий на сайт сообщества.
Такой подход помимо упрощения работы контент-менеджеру (ему не придется загружать фотографии на несколько ресурсов одновременно) также позволяет снять часть за счет того, что фотографии будут загружаться с CDN сети Facebook. Так же, в перспективе это позволит ванлайферам самим делиться своими фото используя свои альбомы в Facebook.
О том как это было сделано — рассказано ниже.
Суть задачи и ее решение
Изначально Facebook предлагает возможность поделится своими альбомами с незарегистрированными пользователями по специальной ссылке которая находится внизу под списком фотографий:
Альбомы групп практически всегда доступны по прямой ссылке которую можно получить просто зайдя в альбом и скопировав url из адресной строки. Именно по этим ссылкам и будет производится разбор альбомов.
К сожалению у Facebook нет публичного rss представления для альбома, поэтому разбирать придется достаточно запутанный и громоздкий код. (Хотя как позже оказалось — запутанный и громоздкий он только на первый взгляд, на самом деле он достаточно хорошо поддается разбору).
Для интереса рекомендую посмотреть исходный код любого альбома что бы понимать с чем именно придется иметь дело.
Там вы увидите огромное количество html кода. Часть из которого закоментированна:
Но как оказалось — именно в этом закоментированном коде и находится необходимая информация об альбоме, которая после загрузки страницы в браузер обрабатывается джава-скриптом.
Так же стоит обратить внимание на то, что запрос должен общаться с хедером, соответствующим одному из современных бразуреов, иначе можете вместо альбома получить страницу с сообщением, что ваш браузер не поддерживает джаваскрипт.
На данный момент мною реализован метод разбора, который позволяет получить название альбома, список полноразмерных фотографий и их preview.
public static Album LoadFromFacebook(string albumPublicLink)
{
var webClient = new WebClient();
webClient.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 5.2; .NET CLR 4.0;)");
webClient.Encoding = Encoding.UTF8;
var html = webClient.DownloadString(albumPublicLink);
var title = Regex.Match(html, "<title>(.*)</title>").Value; //Album title
var photoList = new List<String>();
var resultList2 = new List<String>();
var resultList3 = new List<String>();
var regexObj1 = new Regex(@"(&src=(?<url>(.*?))s*_(n|o).jpg)"); //Big photos
var regexObj2 = new Regex(@"(data-src=""(?<url>(.*?))s*_a.jpg)"); //Preview
var regexObj3 = new Regex(@"<i style=""background-image: url((?<url>(.*?)jpg));""></i>"); //Preview
var matchResult1 = regexObj1.Match(html);
var matchResult2 = regexObj2.Match(html);
var matchResult3 = regexObj3.Match(html);
while (matchResult1.Success)
{
var link = HttpUtility.UrlDecode(matchResult1.Value.Replace("&src=", String.Empty));
photoList.Add(link);
matchResult1 = matchResult1.NextMatch();
}
while (matchResult2.Success)
{
var link = HttpUtility.UrlDecode(matchResult2.Value.Replace("data-src="", String.Empty));
resultList2.Add(link);
matchResult2 = matchResult2.NextMatch();
}
while (matchResult3.Success)
{
var link = HttpUtility.UrlDecode(matchResult3.Value.Replace("<i style="background-image: url(", String.Empty)).Replace(");"></i>", String.Empty).Trim();
resultList3.Add(link);
matchResult3 = matchResult3.NextMatch();
}
var previewList = new List<string>(); //List for merged preview array
previewList.AddRange(resultList2);
previewList.AddRange(resultList3);
var photos = new List<Photo>();
for (int i = 0; i < photoList.Count; i++)
{
var url = photoList[i];
//Find file name i.e. 123423_32435_4543
var resultString = Regex.Match(url, @"/(?<key>(w*))(n|o|a).jpg").Groups["key"].Value;
//Find preview for big photo
var previewUrl = (from o in previewList
where Regex.Match(o, @"/(?<key>(w*))(n|o|a).jpg").Groups["key"].Value == resultString
select o).SingleOrDefault();
photos.Add(new Photo
{
PreviewUrl = previewUrl,
Url = url
});
}
var description = String.Empty;
var album = new Album(title, description, photos);
return album;
}
В дальнейшем планирую я так же добавить возможность вытягивать описания к фото.
Пример реализации
Посмотреть что из этого получилось можно тут:
Код примера можно скачать тут.
В примерах использовались фотографии из альбома Артемия Сурина — основателя движения One Star Life.
Автор: Ernado