По работе получил задание: раскрутить портал. Неправильная верстка, нетранслитная ссылочная структура конечно будут весомыми факторами отсутствия сайта в топе. Не менее весомым обстоятельством, влияющим на позиции портала, оказалось полное отсутствие ссылок с внешних ресурсов (я уже не говорю о близких по тематике). Решение этой задачи было решено автоматизировать.

Я предложил следующий вариант алгоритма своего злобоскрипта: пройтись по карте сайта, преобразовать ее в массив урлов (т.е. все доступные для индексации страницы сайта), из каждой страницы взять метаданные (теги description и keywords), осуществить по содержанию метатегов поиск (автоматический поиск легко реализовать в яндексе) что бы найти близкие по тематике страницы, для каждой из найденных страниц узнать PageRank сайта и есть ли в ней поля ввода (textarea), ну и соответственно сохранить все в лог-файл. После чего согласно лог-файла необходимо разместить ссылки на свои страницы (уже руками) по выданным адресам.

Идею оценили и я принялся за дело. В этой статье дабы не раскрывать коммерческой тайны (какие сайты мною раскручиваются) для наглядности (а заодно и для личной выгоды) пример рассмотрю применительно к раскрутке своего блога.

Что бы не валить все в одну кучу, разделим нашу задачу на несколько подзадач, а именно:
  • Получение ссылок из карты сайта;
  • Парсинг страницы на предмет метатегов (применительно к блогу будем обрабатывать заголовки);
  • Парсинг выдачи поисковика по заданному запросу;
  • Определение авторитетности страницы (или ресурса);
  • Определение наличия полей ввода.

Оформим каждый из этих пунктов в виде функции и поместим их в отдельный модуль (я обозвал его seo.py):

# -*- coding: utf-8
 
import re
import string
import urllib
import urllib2
 
# проверка ссылки на поле ввода
def checkinp(url):
    if url[:7] != 'http://':
        url = 'http://' + url
    try:
        page = urllib.urlopen(url).read()
    except:
        return False
    else:
        pass
    return '<textarea' in page
 
# главный домен страницы
def host(url):
    if url[:7] == 'http://':
url =  url[7:]
    url = string.split(url, '/')[0]
    return 'http://'+url
 
# поиск в яндексе
# page - номер страницы поиска
# numdoc - количество ссылок на странице (20, 50)
def ypages(text, page=0, numdoc=10, results=[]):
    host = «yandex.ru/yandsearch»
    headers = { 'User-Agent' : 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.2.15 Version/10.00',
    'Host' : 'ya.ru',
    'Accept' : 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
    'Accept-Language' : 'ru-RU,ru;q=0.9,en;q=0.8',
    'Accept-Charset' : 'Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1',
    'Referer' : 'http://www2.amit.ru/forum/index.php',
    'Connection' : 'Keep-Alive, TE',
    'TE' : 'TE: deflate, gzip, chunked, identity, trailers' }
 
    if page != 0:
     url = urllib.urlencode({«p»: str(page), «text»: text, «lr»:«77», «numdoc»:str(numdoc)})
    else:
     url = urllib.urlencode({«text»: text, «lr»:«77», «numdoc»:str(numdoc)})
    request = host+"?"+url
    data = urllib2.urlopen(request)
 
    txt = data.read()
    links = re.findall(r'href=«http://([^»]+)', txt)
    for link in links:
     if 'yandex' not in link and link not in results:
         results.append(link)
    return results
 
# убираем частоповторяющиеся выражения (в заголовках)
def del_strs(title):
    not_words = ['-рецепты.', 'Модуль quotes.', 'Цитадель Зла', '.']
    for word in not_words:
if word in title:
            title = string.replace(title, word, '')
    return title
 
# получаем заголовок на странице
def get_title(url):
    page = urllib.urlopen(url).read()
    titles = re.findall(r'<h2 class=«title»>([^<]+)', page)
    return del_strs(titles[0])
 
# ссылки из карты сайта
def sitemap_links(url):
    sitemap = urllib.urlopen(url).read()
    urls = re.findall(r'([^<]+)<', sitemap)
    return urls
 
# эта и последующие функции - для вычисления pagerank
def get_pagerank(url):
    hsh = check_hash(hash_url(url))
    gurl = 'http://www.google.com/search?client=navclient-auto&features=Rank:&q=info:%s&ch=%s' % (urllib.quote(url), hsh)
    try:
        f = urllib.urlopen(gurl)
        rank = f.read().strip()[9:]
    except Exception:
        rank = 'N/A'
    if rank == '':
        rank = '0'
    return rank
 
def  int_str(string, integer, factor):
    for i in range(len(string)) :
        integer *= factor
        integer &= 0xFFFFFFFF
        integer += ord(string[i])
    return integer
 
def hash_url(string):
    c1 = int_str(string, 0x1505, 0x21)
    c2 = int_str(string, 0, 0x1003F)
    c1 >>= 2
    c1 = ((c1 >> 4) & 0x3FFFFC0) | (c1 & 0x3F)
    c1 = ((c1 >> 4) & 0x3FFC00) | (c1 & 0x3FF)
    c1 = ((c1 >> 4) & 0x3C000) | (c1 & 0x3FFF)
    t1 = (c1 & 0x3C0) << 4
    t1 |= c1 & 0x3C
    t1 = (t1 << 2) | (c2 & 0xF0F)
    t2 = (c1 & 0xFFFFC000) << 4
    t2 |= c1 & 0x3C00
    t2 = (t2 << 0xA) | (c2 & 0xF0F0000)
    return (t1 | t2)
 
def check_hash(hash_int):
    hash_str = '%u' % (hash_int)
    flag = 0
    check_byte = 0
    i = len(hash_str) - 1
    while i >= 0:
        byte = int(hash_str[i])
        if 1 == (flag % 2):
            byte *= 2;
            byte = byte / 10 + byte % 10
        check_byte += byte
        flag += 1
        i -= 1
    check_byte %= 10
    if 0 != check_byte:
        check_byte = 10 - check_byte
        if 1 == flag % 2:
            if 1 == check_byte % 2:
                check_byte += 9
            check_byte >>= 1
    return '7' + str(check_byte) + hash_str


А вот и основной скрипт, который и творит все действо:

# -*- coding: utf-8
import seo
import urllib
 
# имя файла-отчета (лог)
fname = 'result.csv'
# адрес карты сайта
sitemap = 'http://toly-blog.ru/sitemap.xml'
# функция занесения строки в лог-файл
def log(st):
    global fname
    f = open(fname, 'a+')
    f.write(st+'\n')
    f.close()
 
# пишем в лог шапку таблицы
log('pr_host;pr_page;url;link\n')
 
# считываем ссылки сайта из карты сайта
urls = seo.sitemap_links(sitemap)
# для каждой страницы сайта
for url in urls:
    print url
    # определяем заголовок страницы
    title = seo.get_title(url)
    if title == 'Рубрики':
continue
    print title
    # ищем заголовок в яндексе
    links = seo.ypages(title)
    # для каждой найденной страницы
    for link in links:
# если есть поля ввода
if seo.checkinp(link):
            # определяем ee pagerank 
            pr_page = str(seo.get_pagerank(link))
    # и pagerank ее хоста
    pr_host = str(seo.get_pagerank(seo.host(link)))
    # оформляем и пишем в лог
    st = pr_host+';'+pr_page+';'+url+';'+link
    log(st)


И вот по окончании работы скрипта получаем аккуратный csv-файл из которого понятно куда, какую ссылку и с какой выгодой можно оставить в комментариях (или на форуме). Можно отфильтровать полученные результаты по PR (PageRank) полученных страниц.

image