Раскручиваем сайт злобоскриптом на питоне


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

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

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

Что бы не валить все в одну кучу, разделим нашу задачу на несколько подзадач, а именно:

  1. Получение ссылок из карты сайта;
  2. Парсинг страницы на предмет метатегов (применительно к блогу будем обрабатывать заголовки);
  3. Парсинг выдачи поисковика по заданному запросу;
  4. Определение авторитетности страницы (или ресурса);
  5. Определение наличия полей ввода.

Оформим каждый из этих пунктов в виде функции и поместим их в отдельный модуль (я обозвал его 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 = "http://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'<loc>([^<]+)<', 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)

Запускаю скрипт и иду пить кофе…

SEO-zloboscript

SEO-zloboscript в работе

Попив кофе приходится налить вторую кружку: очень уж долго без многопоточности все работает.

И вот по окончании работы скрипта получаем аккуратный csv-файл из которого понятно куда какую ссылку можно оставить в комментариях:

Результат работы злобоскрипта

Результат работы злобоскрипта

Жду вопросов и комментариев. Так же хотелось бы услышать предложения по улучшению алгоритма скрипта.

P.S. В коде намеренно допущена ошибка (а может и несколько ошибок – не помню), которые не позволяют использовать скрипт на полную катушку.

P.S. 2 Пробую пробиться на хабр :)

P.S. 3 Не пускают :(

, ,



  1. #1 by pjm on 18 Август 2010 - 3:16

    скрипт по исправлению кривокосорукости?:)

  2. #2 by vedmaka on 23 Май 2011 - 16:58

    Нереально читать , исправьте шрифт!

(никто не узнает)