Created
October 8, 2019 17:57
-
-
Save zilista/aaf76c974521f4d03cfb0b6632b63550 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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