В mongoengine вам следует просто использовать экземпляр ссылочного объекта. Он должен иметь идентификатор. Предположим, что автор является экземпляром документа Author. Поэтому, используя это:
Post.objects(author__eq=author)
, вы можете просмотреть все сообщения этого автора. Post.author должен быть определен как ReferenceField
Вы не можете разобрать [X] HTML с помощью регулярного выражения. Потому что HTML не может быть проанализирован с помощью регулярного выражения. Regex не является инструментом, который можно использовать для правильного синтаксического анализа HTML. Как я уже много раз отвечал на вопросы HTML и регулярных выражений, использование регулярных выражений не позволит вам использовать HTML. Регулярные выражения - это инструмент, который недостаточно сложен для понимания конструкций, используемых HTML. HTML не является обычным языком и поэтому не может быть проанализирован с помощью регулярных выражений. Запросы с регулярными выражениями не способны разбивать HTML на его значимые части. столько раз, но меня это не касается. Даже усовершенствованные нерегулярные регулярные выражения, используемые Perl, не подходят для анализа HTML. Ты никогда не заставишь меня сломаться. HTML - это язык с достаточной сложностью, поэтому его нельзя проанализировать с помощью регулярных выражений. Даже Джон Скит не может анализировать HTML с помощью регулярных выражений. Каждый раз, когда вы пытаетесь разобрать HTML с помощью регулярных выражений, нечестивый ребенок плачет кровью девственниц, и русские хакеры взламывают ваше веб-приложение. Анализ HTML с помощью регулярного выражения вызывает испорченные души в царство живых. HTML и регулярное выражение идут рука об руку, как любовь, брак и ритуальное детоубийство.
Пробовали ли вы использовать вместо него синтаксический анализатор XML?
Примечание модератора
Это сообщение заблокировано, чтобы предотвратить несоответствующие изменения его содержания. Пост выглядит именно так, как и должен выглядеть - проблем с его содержанием нет. Пожалуйста, не обращайте на это внимания.
Мне кажется, вы пытаетесь сопоставить теги без "/" в конце. Попробуйте следующее:
<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
W3C объясняет синтаксический анализ в форме псевдо-регулярного выражения:
Ссылка W3C
Перейдите по ссылкам var для QName
, S
и Атрибут
для получения более четкого изображения.
На основе этого вы можете создать довольно хорошее регулярное выражение для обработки таких вещей, как удаление тегов.
Вы хотите, чтобы перед первым >
не ставился /
. Посмотрите здесь , чтобы узнать, как это сделать. Это называется отрицательным ретроспективным просмотром.
Однако наивная реализация этого приведет к сопоставлению
в этом примере документа
<foo><bar/></foo>
. Не могли бы вы предоставить немного больше информации о проблема, которую вы пытаетесь решить? Вы программно перебираете теги?
Раньше я использовал инструмент с открытым исходным кодом под названием HTMLParser . Он разработан для анализа HTML различными способами и достаточно хорошо выполняет эту задачу. Он может анализировать HTML как разные триноды, и вы можете легко использовать его API для получения атрибутов из узла. Проверьте это и посмотрите, поможет ли это вам.
<?php
$selfClosing = explode(',', 'area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed');
$html = '
<p><a href="#">foo</a></p>
<hr/>
<br/>
<div>name</div>';
$dom = new DOMDocument();
$dom->loadHTML($html);
$els = $dom->getElementsByTagName('*');
foreach ( $els as $el ) {
$nodeName = strtolower($el->nodeName);
if ( !in_array( $nodeName, $selfClosing ) ) {
var_dump( $nodeName );
}
}
Вывод:
string(4) "html"
string(4) "body"
string(1) "p"
string(1) "a"
string(3) "div"
В основном просто определите имена узлов элементов, которые являются самозакрывающимися, загружают всю строку html в библиотеку DOM, захватывают все элементы, проходят цикл и отфильтровывают те, которые не являются самозакрывающимися, и работают с ними.
Я уверен, что вы уже знаете к настоящему времени вы не должны использовать регулярное выражение для этой цели.
Я не знаю, в чем конкретно вам это нужно, но если вы также используете .NET, не могли бы вы использовать Html Agility Pack ?
Отрывок:
Это библиотека кода .NET, которая позволяет вы должны разбирать HTML "вне Интернета" файлы. Парсер очень терпимый с "реальным" искаженным HTML.
Попробуйте:
<([^\s]+)(\s[^>]*?)?(?<!/)>
Он похож на ваш, но последний >
не должен стоять после косой черты, а также принимает h1
.
Я предлагаю использовать QueryPath для синтаксического анализа XML и HTML в PHP. По сути, это тот же синтаксис, что и jQuery, только на стороне сервера.
Если вам это нужно для PHP:
Функции PHP DOM не будут работать должным образом, если они не будут правильно отформатированы в XML. Неважно, насколько лучше их использование для остального человечества.
simplehtmldom - это хорошо, но я обнаружил, что он немного глючит, и он требует большого объема памяти [Будет вылетать на больших страницах.]
Я никогда не использовал querypath , поэтому не могу комментировать его полезность.
Еще один вариант, который стоит попробовать - мой DOMParser , который очень мало использует ресурсы, и какое-то время я с удовольствием использую его. Простой в освоении и мощный.
Для Python и Java были опубликованы похожие ссылки.
Для тех, кто проголосовал против - я написал свой класс только тогда, когда парсеры XML оказались неспособными выдержать реальное использование.
Заявление об ограничении ответственности : используйте синтаксический анализатор, если у вас есть возможность. Тем не менее ...
Это регулярное выражение, которое я использую (!) Для сопоставления тегов HTML:
<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>
Возможно, он не идеален, но я прогнал этот код через лот HTML. Обратите внимание, что он даже улавливает странные вещи, такие как
, которые появляются в Интернете.
Я думаю, чтобы он не соответствовал самодостаточным тегам, вы либо захотите использовать отрицательный взгляд назад Коби :
<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+(?<!/\s*)>
или просто комбинировать, если и если нет.
Тем, кто проголосовал против: Это рабочий код реального продукта. Я сомневаюсь, что кто-то читает это создаст впечатление, что использование регулярных выражений в HTML социально приемлемо.
Предостережение : я должен отметить, что это регулярное выражение все еще не работает при наличии блоков CDATA, комментариев, и элементы сценария и стиля. Хорошие новости: от них можно избавиться с помощью регулярного выражения ...
Хотя произвольный HTML с одним регулярным выражением невозможен, иногда уместно использовать их для синтаксического анализа ограниченного, известного набора HTML. .
Если у вас есть небольшой набор HTML-страниц, с которых вы хотите очистить данные, а затем поместить их в базу данных, регулярные выражения могут работать нормально. Например, недавно я хотел получить имена, партии и округа австралийских федеральных представителей, которые я получил с веб-сайта парламента. Это была ограниченная разовая работа.
Регулярные выражения у меня отлично работали, и их очень быстро настраивали.
Если у вас есть небольшой набор HTML-страниц, с которых вы хотите очистить данные, а затем поместить их в базу данных, регулярные выражения могут работать нормально. Например, недавно я хотел получить имена, партии и округа австралийских федеральных представителей, которые я получил с веб-сайта парламента. Это была ограниченная разовая работа.
Регулярные выражения у меня отлично работали, и их очень быстро настраивали.
Если у вас есть небольшой набор HTML-страниц, с которых вы хотите очистить данные, а затем поместить их в базу данных, регулярные выражения могут работать нормально. Например, недавно я хотел получить имена, партии и округа австралийских федеральных представителей, которые я получил с веб-сайта парламента. Это была ограниченная разовая работа.
Регулярные выражения у меня отлично работали, и их очень быстро настраивали.
Я думаю, что недостаток здесь в том, что HTML - это грамматика Хомского типа 2 (контекстно-свободная грамматика) , а RegEx - это грамматика Хомского типа 3 (обычная грамматика) . Поскольку грамматика типа 2 фундаментально более сложна, чем грамматика типа 3 (см. иерархию Хомского ), математически невозможно проанализировать XML с помощью RegEx.
Но многие будут пытаться, некоторые даже заявят об успехе - но пока другие не найдут вину и полностью вас не собьют.
Поскольку грамматика типа 2 фундаментально сложнее, чем грамматика типа 3 (см. иерархию Хомского ), математически невозможно проанализировать XML с помощью RegEx.Но многие будут пытаться, некоторые даже заявят об успехе, но до тех пор, пока другие не найдут вину и полностью вас не собьют.
Поскольку грамматика типа 2 фундаментально более сложна, чем грамматика типа 3 (см. иерархию Хомского ), математически невозможно проанализировать XML с помощью RegEx.Но многие будут пытаться, некоторые даже заявят об успехе - но пока другие не найдут вину и полностью вас не собьют.
Когда мне нужно быстро извлечь что-то из HTML-документа, я использую Tidy для преобразования его в XML, а затем использую XPath или XSLT, чтобы получить то, что мне нужно. В вашем случае это будет примерно так:
//p/a[@href='foo']
Хотя ответы, которые нельзя разобрать HTML с помощью регексов, правильны, здесь они не применяются. Операционная система просто хочет разобрать один HTML-тег с помощью регексов, и это то, что можно сделать с помощью регулярного выражения.
Предлагаемый регекс неверен, однако:
<([a-z]+) *[^/]*?>
Если вы добавите что-то в регекс, путем обратного слежения он может быть вынужден соответствовать таким глупым вещам, как >
, [^/]
- это слишком неудобно. Также обратите внимание, что <пробел>*[^/]*
является избыточным, так как [^/]*
может также совпадать с пробелами.
Мое предложение было бы
<([a-z]+)[^>]*(?<!/)>
Где (? - это (в регексах Perl) отрицательный взгляд сзади. Оно гласит "a <, затем слово, затем все, что не является a >, последним из которых может не быть a /, за которым следует >".
Обратите внимание, что это разрешает такие вещи как (так же как и оригинальный регекс), так что если Вы хотите что-то более ограничительное, Вам нужно построить регекс, чтобы соответствовать парам атрибутов, разделенным пробелами.
Как уже указывали многие, HTML не является обычным языком, что может сильно затруднить его разбор. Мое решение заключается в том, чтобы превратить его в обычный язык с помощью аккуратной программы, а затем использовать парсер XML для получения результатов. Для этого есть много хороших вариантов. Моя программа написана с использованием Java с библиотекой jtidy для преобразования HTML в XML, а затем Jaxen для xpath в результат.
Хотя использование регулярных выражений для этой цели не подходит и неэффективно, иногда регулярные выражения обеспечивают быстрое решение простых проблем совпадения и, на мой взгляд, использование регулярных выражений для тривиальных работ не так уж и ужасно.
Есть окончательный пост в блоге о согласовании внутренних элементов HTML, написанный Стивеном Левитаном.
В оболочке вы можете проанализировать HTML с помощью sed :
По теме (почему не следует использовать совпадение регулярных выражений):
Здесь есть несколько хороших регулярных выражений для замены HTML на BBCode . Для всех, кто говорит против, обратите внимание, что он не пытается полностью разобрать HTML, просто чтобы дезинфицировать его. Он, вероятно, может позволить себе уничтожить теги, которые его простой "синтаксический анализатор" не может понять.
Например:
$store =~ s/http:/http:\/\//gi;
$store =~ s/https:/https:\/\//gi;
$baseurl = $store;
if (!$query->param("ascii")) {
$html =~ s/\s\s+/\n/gi;
$html =~ s/<pre(.*?)>(.*?)<\/pre>/\[code]$2\[\/code]/sgmi;
}
$html =~ s/\n//gi;
$html =~ s/\r\r//gi;
$html =~ s/$baseurl//gi;
$html =~ s/<h[1-7](.*?)>(.*?)<\/h[1-7]>/\n\[b]$2\[\/b]\n/sgmi;
$html =~ s/<p>/\n\n/gi;
$html =~ s/<br(.*?)>/\n/gi;
$html =~ s/<textarea(.*?)>(.*?)<\/textarea>/\[code]$2\[\/code]/sgmi;
$html =~ s/<b>(.*?)<\/b>/\[b]$1\[\/b]/gi;
$html =~ s/<i>(.*?)<\/i>/\[i]$1\[\/i]/gi;
$html =~ s/<u>(.*?)<\/u>/\[u]$1\[\/u]/gi;
$html =~ s/<em>(.*?)<\/em>/\[i]$1\[\/i]/gi;
$html =~ s/<strong>(.*?)<\/strong>/\[b]$1\[\/b]/gi;
$html =~ s/<cite>(.*?)<\/cite>/\[i]$1\[\/i]/gi;
$html =~ s/<font color="(.*?)">(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<font color=(.*?)>(.*?)<\/font>/\[color=$1]$2\[\/color]/sgmi;
$html =~ s/<link(.*?)>//gi;
$html =~ s/<li(.*?)>(.*?)<\/li>/\[\*]$2/gi;
$html =~ s/<ul(.*?)>/\[list]/gi;
$html =~ s/<\/ul>/\[\/list]/gi;
$html =~ s/<div>/\n/gi;
$html =~ s/<\/div>/\n/gi;
$html =~ s/<td(.*?)>/ /gi;
$html =~ s/<tr(.*?)>/\n/gi;
$html =~ s/<img(.*?)src="(.*?)"(.*?)>/\[img]$baseurl\/$2\[\/img]/gi;
$html =~ s/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/\[url=$baseurl\/$2]$4\[\/url]/gi;
$html =~ s/\[url=$baseurl\/http:\/\/(.*?)](.*?)\[\/url]/\[url=http:\/\/$1]$2\[\/url]/gi;
$html =~ s/\[img]$baseurl\/http:\/\/(.*?)\[\/img]/\[img]http:\/\/$1\[\/img]/gi;
$html =~ s/<head>(.*?)<\/head>//sgmi;
$html =~ s/<object>(.*?)<\/object>//sgmi;
$html =~ s/<script(.*?)>(.*?)<\/script>//sgmi;
$html =~ s/<style(.*?)>(.*?)<\/style>//sgmi;
$html =~ s/<title>(.*?)<\/title>//sgmi;
$html =~ s/<!--(.*?)-->/\n/sgmi;
$html =~ s/\/\//\//gi;
$html =~ s/http:\//http:\/\//gi;
$html =~ s/https:\//https:\/\//gi;
$html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsi;
$html =~ s/\r\r//gi;
$html =~ s/\[img]\//\[img]/gi;
$html =~ s/\[url=\//\[url=/gi;
По вопросу о методах RegExp для синтаксического анализа (x) HTML, ответ на всех, кто говорил о некоторых ограничениях: вы недостаточно обучены, чтобы управлять силой этого мощное оружие, поскольку НИКТО здесь не говорил о рекурсии .
Коллега, не зависящий от RegExp, уведомил меня об этом обсуждении, которое, безусловно, не является первым в сети, посвященным этой старой и горячей теме.
Прочитав несколько сообщений, я первым делом искал строку «? R» в этой ветке. Второй - искать на предмет «рекурсии».
Нет, святая корова, совпадений не найдено.
Поскольку никто не упоминал об основном механизме, на котором построен синтаксический анализатор, я вскоре понял, что никто не понял сути.
Если синтаксическому анализатору (x) HTML требуется рекурсия, синтаксического анализатора RegExp без рекурсии для этой цели недостаточно. Это простая конструкция.
Черное искусство RegExp трудно освоить , так что, возможно, есть дополнительные возможности, которые мы упустили, пытаясь и тестируя наше личное решение для захвата всей сети в одной руке ... Что ж, я конечно :)
Вот волшебный узор:
$pattern = "/<([\w]+)([^>]*?)(([\s]*\/>)|(>((([^<]*?|<\!\-\-.*?\-\->)|(?R))*)<\/\\1[\s]*>))/s";
Просто попробуйте.
Он записывается как строка PHP, поэтому модификатор «s» заставляет классы включать символы новой строки.
Вот пример примечания к руководству по PHP , которое я написал в январе: Ссылка
(Будьте осторожны, в этом примечании я ошибочно использовал модификатор «m»; его следует стереть, несмотря на то, что он отбрасывается механизмом RegExp, поскольку не использовались привязки ^ или $).
Теперь мы могли бы говорить об ограничениях этого метода с более информированной точки зрения:
Так или иначе, это всего лишь шаблон RegExp, но он раскрывает возможность разработки множества мощных реализаций.
Я написал этот шаблон для работы парсера рекурсивного спуска механизма шаблонов, который я построил в своей структуре, и его производительность действительно велика, как по времени выполнения, так и по использованию памяти (ничего общего с другими механизмами шаблонов, которые используют тот же синтаксис).
Вот парсер на основе PHP, который разбирает HTML, используя некий нечестивый regex. Как автор этого проекта, я могу сказать, что парсить HTML с помощью regex можно, но не эффективно. Если вам нужно решение на стороне сервера (как я сделал для своего wp-Typography WordPress plugin), то вот это работает.
Это может сделать:
<.*?[^/]>
Или без закрывающих тегов:
<[^/].*?[^/]>
Что с пламенными войнами в синтаксических анализаторах HTML? Анализаторы HTML должны проанализировать (и перестроить!) Весь документ, прежде чем он сможет классифицировать ваш поиск. При определенных обстоятельствах регулярные выражения могут быть более быстрыми / элегантными. Мои 2 цента ...