Про линки в вики
Nov. 5th, 2017 05:02 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Тут в связи с переездом всех моих сюжетов в единую платформу - fossil, решил заодно проверить, много ли у меня в соотвествующих wiki висячих ссылок.
Написал скриптик:
Результат
Что удивительно - наиболее давно разрабатываемая реальность - самая бедная (тем более что я знаю, что там еще многие существующие страницы нуждаются в серьезной доработке. Я, например на страницу Вента не залил ни одной из нарисованных еще четверть века назад и давно отсканированных карт Венты.
Все плохо и в вики по единственной законченной книге - спейсианской. Там, кстати, могут быть посчитаны не все висячие ссылки, поскольку там присутствуют страницы в формате Fossil Wiki, а вышеприведенный скрипт парсит только markdown.
Написал скриптик:
#!/usr/bin/python # -*- coding: utf-8 -*- """ Поиск висячих ссылок в fossil wiki Запускается из открытого checkout-а. Предполагает что все страницы в формате markdown """ import re,sys,os if sys.stdout.encoding != 'UTF-8': import codecs sys.stdout = codecs.getwriter('utf-8')(sys.stdout, 'strict') from subprocess import Popen,PIPE,CalledProcessError def fossil(args, stdin=None): """ Запускаем fossil с аргументами из списка args. передавая ему на вход строку stdin. Возвращает stdout. Выбрасывает CalledProcessError если fossil-у что-то не понравилось """ p=Popen(["fossil"]+args,stdin=PIPE, stdout=PIPE,stderr=PIPE) (out,err) = p.communicate(stdin) if p.returncode!=0: print >>sys.stderr,err raise CalledProcessError(p.returncode," ".join(["fossil"]+args),err) return out # # Получить список страниц и сконвертирвоать его в ключи словаря со # значениями 1 # pages=dict(map(lambda x:(x,1),fossil(["wiki","list"]).split("\n"))) # # Поскольку в конце вывода fossil wiki list есть перевод строки, # в словаре будет один лишний элемент с пустым ключом del pages[''] print "Wiki contains %d pages" % len(pages.keys()) dangling={} for page in pages: contents = fossil(["wiki","export",page]) for link in re.finditer("\(wiki\?name=([^)]+)\)",contents): linkname=link.group(1).replace("+"," ") linkname=re.sub("%([0-9A-Fa-f]{2})",lambda m:chr(int(m.group(1),16)),linkname) anchor=linkname.find("#") if anchor > -1: linkname=linkname[:anchor] if linkname in pages: continue if linkname in dangling: dangling[linkname].add(page) else: dangling[linkname]=set([page]) print "Found %d dangling links"%len(dangling.keys()) for page in sorted(dangling.keys()): print u"%-40s %s"%(page.decode("utf-8"),",".join(dangling[page]).decode("utf-8"))и погонял его на все репозитории.
Результат
репозиторий | всего страниц | висячих ссылок |
Русалки | 34 | 0 |
Ясмина | 206 | 0 |
Спейсиане | 226 | 122 |
Галактическая Федерация | 76 | 116 |
Что удивительно - наиболее давно разрабатываемая реальность - самая бедная (тем более что я знаю, что там еще многие существующие страницы нуждаются в серьезной доработке. Я, например на страницу Вента не залил ни одной из нарисованных еще четверть века назад и давно отсканированных карт Венты.
Все плохо и в вики по единственной законченной книге - спейсианской. Там, кстати, могут быть посчитаны не все висячие ссылки, поскольку там присутствуют страницы в формате Fossil Wiki, а вышеприведенный скрипт парсит только markdown.
no subject
Date: 2017-11-05 02:25 pm (UTC)pages = set(fossil(["wiki","list"]).split("\n"))
Так ты и от map избаляешься, и от глупой лямбды.
print "Wiki contains %d pages" % len(pages)
no subject
Date: 2017-11-05 04:04 pm (UTC)А вот map и lambda это классика.
Для страниц, на которых есть данная висячая ссылка я догадался использовать set, поскольку увидел что список содержит слишком много дубликатов.
А тут у меня сработал стереотип "нужна структура, позволяющая за константное время проверить наличие в ней элемента. Такая структура называется хэш-таблица. В питоне это dict".
К сожалению, у меня нет достаточно большой wiki, чтобы имело смысл мерить производительность обоих вариантов.
no subject
Date: 2017-11-05 04:37 pm (UTC)pages = {x: 1 for x in fossil(["wiki", "list"]).split("\n")}
no subject
Date: 2017-11-05 04:43 pm (UTC)А comprehension я запомнить не могу. Там синтаксис какой-то, который, видимо, интуитивен для
любителей APLпрофессиональных математиков, но я не знаю, где скачать соответствующее обновление интуиции. Опять же, боюсь, что если я его скачаю, то оно начнет конфликтовать с другими языками, на которых приходится систематически писать.Переключение с питона на perl и обратно всегда происходит матерно. А на тех языках, куда переключение с питона естественно, например java, я не пишу.
no subject
Date: 2017-11-14 08:43 am (UTC)В хаскеле, впрочем, list comprehension используется редко. А вот monad comprehension - в хвост и в гриву, иначе с монадами получается нечитаемый код. А в scala, насколько я могу видеть, и списковый тоже часто.
И код на ней, кстати, ближе к tcl получается.
no subject
Date: 2017-11-14 08:45 am (UTC)no subject
Date: 2017-11-14 02:05 pm (UTC)Пока у тебя ситуация идеальная, шелл, конечно, повыше уровнем будет. На нем в одну строку выражается то, что на приличном ЯВУ занимает 10 (при условии, что у тебя GNU tools, потому что это далеко не на нем самом выражается). Зато в неидеальных на приличном ЯВУ это ну, 20, а на шелле минимум 100, и неидеальность в процессе только прогрессирует. Такой язык я считаю низкоуровневым.
no subject
Date: 2017-11-05 06:20 pm (UTC)Сложно, но возможно - задействовать re...
no subject
Date: 2017-11-06 10:05 am (UTC)