Я работаю над тем, как сделать Google Crawlab доступным на основе инструкций Google . Несмотря на то, что есть довольно много общих объяснений, я нигде не смог найти более подробного пошагового руководства с реальными примерами. После этого я хотел бы поделиться своим решением, чтобы другие тоже могли его использовать и, возможно, улучшить.
Я использую MVC
с Webapi
контроллерами и Phantomjs на стороне сервера, и Durandal на стороне клиента с push-state
включенным; Я также использую Breezejs для взаимодействия данных между клиентом и сервером, что я настоятельно рекомендую, но я постараюсь дать достаточно общее объяснение, которое также поможет людям, использующим другие платформы.
143
Ответы:
Перед началом, пожалуйста, убедитесь, что вы понимаете, что требует Google , в частности, использование красивых и некрасивых URL-адреса. Теперь давайте посмотрим на реализацию:
Сторона клиента
На стороне клиента у вас есть только одна HTML-страница, которая динамически взаимодействует с сервером через вызовы AJAX. вот что такое SPA. Все
a
теги на стороне клиента создаются динамически в моем приложении, позже мы увидим, как сделать эти ссылки видимыми для бота Google на сервере. Каждый такойa
тег должен иметь возможность иметь тегpretty URL
вhref
теге, чтобы бот Google сканировал его. Вы не хотите, чтобы этаhref
часть использовалась, когда клиент нажимает на нее (даже если вы действительно хотите, чтобы сервер мог ее проанализировать, мы увидим это позже), потому что мы можем не захотеть загружать новую страницу, только для вызова AJAX с получением некоторых данных для отображения на части страницы и изменения URL-адреса с помощью JavaScript (например,pushstate
Durandaljs
). Итак, у нас естьhref
Атрибут для Google, а также наonclick
котором выполняет свою работу, когда пользователь нажимает на ссылку. Теперь, поскольку я использую,push-state
я не хочу ничего#
в URL, поэтому типичныйa
тег может выглядеть так:<a href="http://www.xyz.com/#!/category/subCategory/product111" onClick="loadProduct('category','subCategory','product111')>see product111...</a>
«category» и «subCategory», вероятно, будут другими фразами, такими как «связь» и «телефоны» или «компьютеры» и «ноутбуки» для магазина электротоваров. Очевидно, будет много разных категорий и подкатегорий. Как видите, ссылка непосредственно на категорию, подкатегорию и продукт, а не в качестве дополнительных параметров для конкретной страницы «магазина», такой как
http://www.xyz.com/store/category/subCategory/product111
. Это потому, что я предпочитаю более короткие и простые ссылки. Это означает, что у меня не будет категории с тем же именем, что и на одной из моих «страниц», т.е.Я не буду вдаваться в то, как загрузить данные через AJAX (
onclick
часть), искать их в Google, есть много хороших объяснений. Единственная важная вещь, о которой я хочу упомянуть, это то, что когда пользователь нажимает на эту ссылку, я хочу, чтобы URL в браузере выглядел так:http://www.xyz.com/category/subCategory/product111
, И это URL не отправляется на сервер! помните, что это SPA, где все взаимодействие между клиентом и сервером осуществляется через AJAX, никаких ссылок вообще! все «страницы» реализованы на стороне клиента, и другой URL не вызывает сервер (сервер должен знать, как обрабатывать эти URL, если они используются в качестве внешних ссылок с другого сайта на ваш сайт, мы увидим это позже на стороне сервера). Теперь, с этим прекрасно справляется Дюрандаль. Я настоятельно рекомендую это сделать, но вы также можете пропустить эту часть, если предпочитаете другие технологии. Если вы выберете его, и вы также используете MS Visual Studio Express 2012 для Web, как я, вы можете установить Durandal Starter Kit и тамshell.js
использовать что-то вроде этого:Здесь следует отметить несколько важных вещей:
route:''
) является для URL , который не имеет никаких дополнительных данных в нем, то естьhttp://www.xyz.com
. На этой странице вы загружаете общие данные, используя AJAX. Наa
этой странице вообще не может быть никаких тегов. Вы хотите , чтобы добавить следующий тег так бот Google будет знать , что делать с ним:<meta name="fragment" content="!">
. Этот тег заставит бота Google преобразовать URL,www.xyz.com?_escaped_fragment_=
который мы увидим позже.mapUnknownRoutes
приходит. Он сопоставляет эти неизвестные маршруты с маршрутом 'store', а также удаляет любые '!' с URL на случай, если онpretty URL
сгенерирован поисковым движком Google. Маршрут store хранит информацию в свойстве фрагмента и вызывает AJAX для получения данных, их отображения и локального изменения URL. В моем приложении я не загружаю разные страницы для каждого такого вызова; Я изменяю только ту часть страницы, где эти данные имеют отношение, а также меняю местный URL.pushState:true
что Durandal указывает использовать URL-адреса push-состояний.Это все, что нам нужно на стороне клиента. Это может быть реализовано также с хэшированными URL-адресами (в Durandal вы просто удаляете
pushState:true
для этого). Более сложной частью (по крайней мере для меня ...) была серверная часть:Сторона сервера
Я использую
MVC 4.5
на стороне сервера сWebAPI
контроллерами. Сервер фактически должен обрабатывать 3 типа URL: сгенерированные google - оба,pretty
аugly
также «простой» URL того же формата, что и тот, который отображается в браузере клиента. Давайте посмотрим, как это сделать:Красивые и простые URL-адреса сначала интерпретируются сервером, как будто они пытаются сослаться на несуществующий контроллер. Сервер видит что-то подобное
http://www.xyz.com/category/subCategory/product111
и ищет контроллер с именем 'category'. Поэтомуweb.config
я добавляю следующую строку, чтобы перенаправить их на конкретный контроллер обработки ошибок:Теперь это превращает URL в что - то вроде:
http://www.xyz.com/Error?aspxerrorpath=/category/subCategory/product111
. Я хочу, чтобы URL-адрес отправлялся клиенту, который будет загружать данные через AJAX, поэтому хитрость здесь заключается в том, чтобы вызвать контроллер индекса по умолчанию, как если бы он не ссылался на какой-либо контроллер; Я делаю это, добавляя хеш к URL-адресу перед всеми параметрами 'category' и 'subCategory'; Для хешированного URL-адреса не требуется никакого специального контроллера, кроме контроллера по умолчанию «index», и данные отправляются клиенту, который затем удаляет хеш и использует информацию после хеша для загрузки данных через AJAX. Вот код контроллера обработчика ошибок:Но как насчет уродливых URL ? Они создаются ботом Google и должны возвращать простой HTML, который содержит все данные, которые пользователь видит в браузере. Для этого я использую фантомы . Phantom - это безголовый браузер, который делает то же, что и браузер на стороне клиента, но на стороне сервера. Другими словами, фантом знает (среди прочего), как получить веб-страницу через URL-адрес, проанализировать ее, включая выполнение всего кода javascript (а также получение данных с помощью вызовов AJAX), и вернуть вам HTML, который отражает ДОМ. Если вы используете MS Visual Studio Express, многие хотят установить фантом по этой ссылке .
Но сначала, когда на сервер отправляется некрасивый URL, мы должны его перехватить; Для этого я добавил в папку «App_start» следующий файл:
Это вызывается из 'filterConfig.cs' также в 'App_start':
Как вы можете видеть, AjaxCrawlableAttribute направляет некрасивые URL-адреса на контроллер с именем «HtmlSnapshot», и вот этот контроллер:
Это
view
очень просто, всего одна строка кода:@Html.Raw( ViewBag.result )
как вы можете видеть в контроллере, фантом загружает файл javascript с именем
createSnapshot.js
в созданной мной папке с именемseo
. Вот этот файл JavaScript:Сначала я хочу поблагодарить Томаса Дэвиса за страницу, с которой я получил основной код :-).
Здесь вы заметите нечто странное: фантом продолжает перезагружать страницу, пока
checkLoaded()
функция не вернет true. Это почему? это потому, что мой специальный SPA делает несколько AJAX-вызовов, чтобы получить все данные и поместить их в DOM на моей странице, и фантом не может знать, когда все вызовы завершены, прежде чем вернуть мне обратно HTML-отражение DOM. То, что я сделал здесь, после последнего вызова AJAX, я добавляю a<span id='compositionComplete'></span>
, так что если этот тег существует, я знаю, что DOM завершен. Я делаю это в ответ наcompositionComplete
событие Дюрандаля , см. здесьдля большего. Если этого не произойдет в течение 10 секунд, я сдаюсь (это займет всего одну секунду, чтобы максимально). Возвращенный HTML-код содержит все ссылки, которые пользователь видит в браузере. Сценарий не будет работать должным образом, поскольку<script>
теги, которые существуют в снимке HTML, не ссылаются на правильный URL-адрес. Это также может быть изменено в фантомном файле javascript, но я не думаю, что это необходимо, потому что моментальный снимок HTML используется Google только для полученияa
ссылок, а не для запуска javascript; эти ссылки делают ссылаться на довольно URL, и если самом деле, если вы пытаетесь увидеть HTML снимок в браузере, вы получите JavaScript ошибки , но все ссылки будут работать должным образом и направить вас на сервер еще раз с симпатичной URL на этот раз получить полностью рабочую страницу.это все. Теперь сервер знает, как обрабатывать как красивые, так и некрасивые URL, с включенным push-состоянием как на сервере, так и на клиенте. Все уродливые URL обрабатываются одинаково с использованием фантома, поэтому нет необходимости создавать отдельный контроллер для каждого типа вызова.
Одна вещь , которую вы могли бы предпочесть изменения не сделать созвать общее «категорию / подкатегорию / продукт» , но , чтобы добавить «магазин» так , что ссылка будет выглядеть примерно так:
http://www.xyz.com/store/category/subCategory/product111
. Это позволит избежать проблемы в моем решении, заключающейся в том, что все недопустимые URL-адреса обрабатываются так, как будто они на самом деле являются вызовами контроллера «index», и я предполагаю, что они могут быть обработаны затем в контроллере «store» без добавления к тому, чтоweb.config
я показал выше. ,источник
Google теперь может отображать страницы SPA: устарела наша схема сканирования AJAX
источник
Вот ссылка на скринкаст с моего учебного класса Ember.js, который я провел в Лондоне 14 августа. В нем изложена стратегия как для вашего клиентского приложения, так и для вашего серверного приложения, а также дается живая демонстрация того, как реализация этих функций обеспечит вашему одностраничному приложению JavaScript постепенную деградацию даже для пользователей с отключенным JavaScript ,
Он использует PhantomJS, чтобы помочь в сканировании вашего сайта.
Короче говоря, необходимые шаги:
После того, как этот шаг будет выполнен, ваш сервер сможет использовать статическую версию HTML как часть тега noscript на этой странице. Это позволит Google и другим поисковым системам сканировать каждую страницу на вашем сайте, даже если ваше приложение изначально представляет собой приложение на одну страницу.
Ссылка на скринкаст с полной информацией:
http://www.devcasts.io/p/spas-phantomjs-and-seo/#
источник
Вы можете использовать или создать свой собственный сервис для предоплаты вашего SPA с помощью сервиса под названием prerender. Вы можете проверить это на его сайте prerender.io и в его проекте github. (он использует PhantomJS и обновляет ваш сайт для вас).
Это очень легко начать с. Вам нужно только перенаправить запросы сканерам в службу, и они получат визуализированный html.
источник
Вы можете использовать http://sparender.com/, что позволяет правильно сканировать одностраничные приложения.
источник