Skip to content

Instantly share code, notes, and snippets.

@zilista
Created October 8, 2019 17:57
Show Gist options
  • Save zilista/aaf76c974521f4d03cfb0b6632b63550 to your computer and use it in GitHub Desktop.
Save zilista/aaf76c974521f4d03cfb0b6632b63550 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Описание файла"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Данный способ подходит для случаев, когда необходимо быстро запустить и протестировать турбо-страницы. Рекомендуется использовать скрипт для генерации rss-канала для страниц статейных сайтов, контент которых изменяет редко. \n",
"\n",
"Плюсы данного подхода:\n",
"- Быстрое внедрение. Не требуется помощь программиста.\n",
"- Не нужно подключение к базе, где хранится контент. Весь контент и его разметку берем прямо со страниц.\n",
"- Используем стандарные seo-инструменты\n",
"\n",
"Минусы:\n",
"- Необновляемый xml-файл. После измения контента требуется пересобирать контент и формировать новый xml.\n",
"- Новые страницы также не будут попадать в файл. Для них будет необходимо заново парсить контент и формировать xml\n",
"\n",
"Ниже описана последовательность работ."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Подготавливаем данные для генерации файла"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 1. С помощью screaming frog парсим контент страниц, для которых будем подключать турбо-страницы.\n",
"\n",
"На этом этапе подготавливаем данные для обязательных элементов, необходимых при формировании xml-файла. \n",
"\n",
"Обязательные поля:\n",
"- link. URL страницы сайта, для которой нужно сформировать Турбо-страницу.\n",
"- h1. Заголовок страницы.\n",
"- turbo:content. Содержимое страницы.\n",
"\n",
"Подробнее на странице https://yandex.ru/dev/turbo/doc/rss/simple-rss-docpage/\n",
"\n",
"\n",
"\n",
"Использую xpath парсим контент страниц со всех html-разметкой. Копируем через панель разработчика или пищем свой запрос (//div[@class='entry-content entry--item'])\n",
"\n",
"\n",
"\n",
"\n",
"Экспортирем полученные данные в csv."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Подключаем нужные библиотеки"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import csv\n",
"import pandas as pd\n",
"import os\n",
"import math"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"data = pd.read_csv('internal_all - internal_all.csv') #дописать \", header=1\", если проблема при считывании заголовка\n",
"data = data[['Address', 'H1-1', 'текст 1']]\n",
"\n",
"## Если в таблицу попали лишние страницы, их можно легко отфильтровать. Ниже примеры.\n",
"# data = data[data['Status Code']==200]\n",
"# data = data[~data['Address'].str.contains('page')]\n",
"# data = data.drop(index=0)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Всего в файле строк: 118\n",
"Будет сгенерировано xml-файлов: 1\n"
]
}
],
"source": [
"rows_in_rss = 1000 # количество строк в одном rss-канале\n",
"total_rows = len(data) - 1\n",
"total_xml_file = math.ceil((total_rows-1)/rows_in_rss)\n",
"\n",
"print('Всего в файле строк:', total_rows)\n",
"print('Будет сгенерировано xml-файлов:', total_xml_file)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 2. Формируем структуру RSS-канала\n",
"\n",
"Создаем функцию create_xml отвечающую за создание начала файла"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def create_xml(item_count_next):\n",
" rss_file = open('rss{:.0f}.xml'.format(item_count_next/rows_in_rss), 'w', encoding=\"utf-8\")\n",
" rss_file.write(\n",
" \"\"\"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
" <rss xmlns:yandex=\"http://news.yandex.ru\"\n",
" xmlns:media=\"http://search.yahoo.com/mrss/\"\n",
" xmlns:turbo=\"http://turbo.yandex.ru\"\n",
" version=\"2.0\">\n",
" <channel>\"\"\")\n",
" rss_file.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Функия close_xml будет закрывать файл"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"def close_xml(item_count_next):\n",
" rss_file = open('rss{:.0f}.xml'.format(item_count_next/rows_in_rss), 'a', encoding=\"utf-8\")\n",
" rss_file.write(\n",
" ' </channel>' + '\\n'+\n",
" '</rss>'\n",
" )\n",
" rss_file.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В функцию data_for_rss передаем номер первой и последней строки. Для этого промежутка будем формировать rss.\n",
"\n",
"Построчно считываем строки в датафрейме и формируем <item\\>, записывая получившиеся данные в xml-файл. Каждая строка в датафрейме - новая страница. "
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"def data_for_rss(item_count_prev, item_count_next):\n",
" \n",
" data_rss = data[item_count_prev:item_count_next]\n",
" \n",
" if len(data_rss) != 0:\n",
" \n",
" with open('rss{:.0f}.xml'.format(item_count_next/rows_in_rss), 'a', encoding=\"utf-8\") as rss_file:\n",
" \n",
" for index, row in data_rss.iterrows():\n",
" \n",
" url = str(row[0])\n",
" \n",
" h1 = str(row[1])\n",
"\n",
" text = str(row[2])\n",
" \n",
" rss_file.write(\"\"\"<item turbo=\"true\">\n",
" <link>\"\"\"+ url + \"\"\"</link>\n",
" <turbo:content>\n",
" <![CDATA[\n",
" <header> <h1>\"\"\"+ h1 +\"\"\"</h1> \n",
" </header>\"\"\"\n",
" + text+ \n",
" \"\"\"<div data-block=\"share\" data-network=\"vkontakte,odnoklassniki,facebook,twitter\"></div>\n",
" ]]>\n",
" </turbo:content>\n",
" </item>\"\"\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Делаем проверку размера получившихся фидов. Размер xml-файла не должен превышать 15MB. В случае, если размер получился больше изменяем количество строк в одном файле, изменяя значение переменной \"rows_in_rss\""
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"def size_file(item_count_next):\n",
" \n",
" size_final_file_MB = os.path.getsize('rss{:.0f}.xml'.format(item_count_next/rows_in_rss))/1024/1024\n",
" \n",
" if size_final_file_MB < 15:\n",
" print('Файл создан')\n",
" else:\n",
" print('Нужно уменьшить шаг')\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Финальный шаг – Генерация фидов."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1\n",
"Файл создан\n"
]
}
],
"source": [
"item_count_prev = 0\n",
"\n",
"item_count_next = 1000 # должен быть равен rows_in_rss\n",
"\n",
"count_rss = 0\n",
"\n",
"print(total_xml_file)\n",
"\n",
"\n",
"while count_rss < total_xml_file:\n",
" \n",
" create_xml(item_count_next)\n",
"\n",
" data_list = data_for_rss(item_count_prev,item_count_next)\n",
"\n",
" close_xml(item_count_next)\n",
" \n",
" size_file(item_count_next)\n",
" \n",
" item_count_prev += rows_in_rss\n",
" \n",
" item_count_next += rows_in_rss\n",
" \n",
" count_rss += 1\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Остается добавить rss в личном кабинете Яндекс Вебмастер и настроить меню, лого, счетчики систем аналитики"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment