Эта статья является оригинальной статьей, перепечатайте и укажите источник, добро пожаловать на сканирование кода и обратите внимание на общедоступный номер
flysnow_orgили сайтwww.flysnow.org/, и впервые прочитал последующие замечательные статьи. Если вы думаете, что это хорошо, пожалуйста, поделитесь им со своим кругом друзей, спасибо за вашу поддержку.
Недавно я изучил знания, связанные с поисковым роботом Go, и я много использовал библиотеку goquery, особенно при выборе просканированного HTML и поиске соответствующего контента, селекторы goquery часто используются, и есть много необычных, но очень полезных селекторов. Полезные селекторы приведены здесь для справки.
Если вы уже занимались фронтенд-разработкой, вы наверняка знакомы с jQuery. Goquery похож на jQuery. Это версия jQuery для перехода. Используя его, вы легко сможете разобраться с HTML.
Селекторы на основе элементов HTML
Это относительно простое, оно основано наa,pПосле выбора этих основных элементов HTML вы можете напрямую использовать имя элемента в качестве селектора. Напримерdom.Find("div").
func main() {
html := `<body>
<div>DIV1</div>
<div>DIV2</div>
<span>SPAN</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
}
Приведенный выше пример может бытьdivэлементы отфильтровываются, аbody,spanи не будет фильтроваться.
Селектор идентификатора
Это наиболее часто используемый, как и в приведенном выше примере, есть дваdivэлемент, на самом деле нам нужен только один из них, то нам нужно только придать этому тегу уникальныйid, поэтому мы можем использоватьidСелектор установлен точно.
func main() {
html := `<body>
<div id="div1">DIV1</div>
<div>DIV2</div>
<span>SPAN</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("#div1").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
}
Селектор идентификатора элемента
idселектор с#в начале, затем элементidзначение, используя синтаксисdom.Find(#id), в следующем примере я буду сокращать его какFind(#id), мы все знаем, что это представляет собой селектор goquery.
Что делать, если есть одинаковые идентификаторы, но они принадлежат разным элементам HTML? Есть хороший способ совместить его с Element. Например, мы фильтруем элементы какdiv,иidдаdiv1элементы, вы можете использоватьFind(div#div1)Такие фильтры являются фильтрующими.
Итак, синтаксис такого фильтра:Find(element#id), который является широко используемым методом комбинирования. Например, фильтры, упомянутые ниже, также могут быть объединены таким образом.
Селектор класса
classЭто также часто используемый атрибут в HTML, мы можем передатьclassселектор для быстрой фильтрации необходимых элементов HTML, их использования иIDселектор похож наFind(".class").
func main() {
html := `<body>
<div id="div1">DIV1</div>
<div class="name">DIV2</div>
<span>SPAN</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find(".name").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
}
В приведенном выше примере отфильтруйтеclassзаnameэтоdivэлемент.
Селектор класса элемента
classселектор иidКак и селекторы, их также можно использовать в сочетании с элементами HTML, и их синтаксис аналогиченFind(element.class), чтобы вы могли фильтровать определенные элементы и указывать элементы класса.
селектор атрибутов
Элемент HTML имеет свои собственные атрибуты и значения атрибутов, поэтому мы также можем фильтровать элементы по атрибутам и значениям.
func main() {
html := `<body>
<div>DIV1</div>
<div class="name">DIV2</div>
<span>SPAN</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div[class]").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
}
В примереdiv[class]Селектор выбран Элементdivи имеютclassэтого свойства, поэтому первоеdivне экранированный.
В приведенном выше примере в качестве фильтра используется наличие определенного атрибута Аналогичным образом мы можем отфильтровать элементы, атрибут которых имеет определенное значение.
dom.Find("div[class=name]").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
Таким образом, мы можем отфильтроватьclassСтоимость свойстваnameизdivэлемент.
Конечно мы здесьclassНапример, можно использовать и другие атрибуты, напримерhrefИ так далее, возможны и настраиваемые свойства.
Помимо полного равенства, есть и другие методы сопоставления, которые используются аналогичным образом, они перечислены здесь и не будут перечислены.
| Селектор | инструкция |
|---|---|
| Find("div[lang]") | Фильтровать элементы div с атрибутом lang |
| Find("div[lang=zh]") | Отфильтровать элементы div, чей атрибут lang равен zh |
| Find("div[lang!=zh]") | Отфильтровать элементы div, атрибут lang которых не равен zh |
| Find("div[lang¦=zh]") | Отфильтровать элементы div, атрибут lang которых начинается с zh или zh- |
| Find("div[lang*=zh]") | Отфильтровать элементы div, атрибут lang которых содержит строку zh |
| Find("div[lang~=zh]") | Отфильтровать элементы div, атрибут lang которых содержит слово zh, а слова разделены пробелами |
| Find("div[lang$=zh]") | Отображение атрибута lang в конце элемента div zh с учетом регистра |
| Find("div[lang^=zh]") | Отфильтровать элементы div, атрибут lang которых начинается с zh, с учетом регистра. |
Выше показано использование фильтров атрибутов, каждый из которых использует один фильтр атрибута в качестве примера. Конечно, вы также можете использовать несколько фильтров атрибутов в комбинации, например:Find("div[id][lang=zh]"), используйте несколько квадратных скобок, чтобы соединить их. При наличии нескольких фильтров атрибутов элементы, одновременно удовлетворяющие этим фильтрам, могут быть отфильтрованы.
родитель>дочерний селектор
Если мы хотим отфильтровать подэлементы, которые соответствуют условиям элемента, мы можем использовать фильтр подэлементов, его синтаксис такой:Find("parent>child"), Указывает на фильтрацию самого прямого (первого уровня) дочернего элемента, который соответствует условию дочернего элемента в родительском элементе parent.
func main() {
html := `<body>
<div lang="ZH">DIV1</div>
<div lang="zh-cn">DIV2</div>
<div lang="en">DIV3</div>
<span>
<div>DIV4</div>
</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("body>div").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
}
Пример выше, отфильтроватьbodyПод этим родительским элементом самый прямой дочерний элемент, который соответствует условиямdiv,оказатьсяDIV1、DIV2、DIV3,Несмотря на то чтоDIV4Слишкомbody, но не первого уровня, поэтому он не будет отфильтровываться.
Итак, вот вопрос, я просто хочуDIV4Тоже проверяю? Что делать? Только проверяюbodyпод всемиdivЭлементы, первичные, вторичные или N-уровня. Есть способ, goquery его учитывает, просто поставьте знак больше (>) заменяется пробелом. Например, приведенный выше пример можно изменить на следующий селектор.
dom.Find("body div").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
предыдущий+следующий соседний селектор
Предположим, что элемент, который мы хотим отфильтровать, является нерегулярным, но предыдущий элемент элемента является регулярным, мы можем использовать этот следующий соседний селектор для выбора.
func main() {
html := `<body>
<div lang="zh">DIV1</div>
<p>P1</p>
<div lang="zh-cn">DIV2</div>
<div lang="en">DIV3</div>
<span>
<div>DIV4</div>
</span>
<p>P2</p>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div[lang=zh]+p").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
}
Этот пример демонстрирует это использование, мы хотим выбрать<p>P1</p>Этот элемент, но шаблона нет, мы обнаружили, что предыдущий<div lang="zh">DIV1</div>Есть правила и выбор, поэтому мы можем использоватьFind("div[lang=zh]+p")достичь выбораPназначение элемента.
Синтаксис этого селектора("prev+next"), со знаком плюс (+) посередине и селекторами до и после знака +.
Эта статья является оригинальной статьей, перепечатайте и укажите источник, добро пожаловать на сканирование кода и обратите внимание на общедоступный номер
flysnow_orgили сайтwww.flysnow.org/, и впервые прочитал последующие замечательные статьи. Некоторые из наиболее постыдных веб-сайтов будут удалять информацию об авторских правах при сканировании моих статей.Я напишу здесь еще один абзац.Пожалуйста, простите меня.
предыдущий~следующий селектор
Если есть соседи, есть и братья.Селектор родственного элемента не обязательно требует соседей, если они имеют общий родительский элемент.
dom.Find("div[lang=zh]~p").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
Просто пример, просто поставь+Замените число на~номер можно поставитьP2Также экранирован, потому чтоP2,P1иDIV1Все братья.
Синтаксис родственного селектора:("prev~next"), то есть соседний селектор+заменяется~.
Фильтр контента
Иногда после того, как мы используем селектор, чтобы выбрать его, мы хотим снова отфильтровать его. В этот раз мы используем фильтр. Существует много фильтров. Давайте сначала поговорим о фильтре содержимого.
dom.Find("div:contains(DIV2)").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
Find(":contains(text)")Указывает, что отфильтрованные элементы должны содержать указанный текст. В нашем примере выбранныйdivэлемент, который будет содержатьDIV2текст, то только одинDIV2Элемент удовлетворяет требованию.
Рядом с этим естьFind(":empty")Указывает, что фильтр не может иметь дочерний элемент (включая текстовый элемент), и фильтруются только те элементы, которые не содержат дочерних элементов.
Find(":has(selector)")иcontainsПочти, но этот содержит узлы элементов.
dom.Find("span:has(div)").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Text())
})
В приведенном выше примере показано, что фильтр содержитdivэлементальspanузел.
: первый дочерний фильтр
:first-childфильтр, синтаксисFind(":first-child"), указывая, что отфильтрованные элементы являются первыми дочерними элементами своих родительских элементов, в противном случае они не будут отфильтрованы.
func main() {
html := `<body>
<div lang="zh">DIV1</div>
<p>P1</p>
<div lang="zh-cn">DIV2</div>
<div lang="en">DIV3</div>
<span>
<div style="display:none;">DIV4</div>
<div>DIV5</div>
</span>
<p>P2</p>
<div></div>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div:first-child").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Html())
})
}
В приведенном выше примере мы используемFind("div")отфильтрует всеdivэлемент, но мы добавили:first-childТолько после этогоDIV1иDIV4потому что только эти два являются первыми детьми их родительских элементов, другиеDIVне удовлетворены.
: фильтр первого типа
:first-childСравнение ограничений селектора мертво, и это должен быть первый дочерний элемент.Если перед элементом есть другие элементы, его нельзя использовать.:first-childсейчас, на этот раз:first-of-typeОн пригодится, он требует, пока он первый из этого типа, мы дорабатываем приведенный выше пример.
func main() {
html := `<body>
<div lang="zh">DIV1</div>
<p>P1</p>
<div lang="zh-cn">DIV2</div>
<div lang="en">DIV3</div>
<span>
<p>P2</p>
<div>DIV5</div>
</span>
<div></div>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div:first-of-type").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Html())
})
}
Изменение очень просто, оригиналDIV4заменяетсяP2, если мы также используем:first-child,DIV5не может быть отфильтрован, потому что это не первый дочерний элемент, у него естьP2. В это время мы используем:first-of-typeОн может достичь своей цели, потому что ему требуется первый такой же тип.DIV5Это оноdivпервый элемент типа,P2нетdivТип, игнорируется.
фильтры :last-child и :last-of-type
Эти два точно такие же, как выше:first-child,:first-of-typeНаоборот, это означает последний.Я не буду приводить здесь пример.Вы можете попробовать сами.
:n-дочерний(n) фильтр
Это означает, что экран является девятым элементом своего родительского элемента, а N начнется в 1. Итак, мы можем знать:first-childи:nth-child(1)равны. указавn, мы можем гибко отфильтровывать нужные нам элементы.
func main() {
html := `<body>
<div lang="zh">DIV1</div>
<p>P1</p>
<div lang="zh-cn">DIV2</div>
<div lang="en">DIV3</div>
<span>
<p>P2</p>
<div>DIV5</div>
</span>
<div></div>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div:nth-child(3)").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Html())
})
}
Этот пример отфильтровываетDIV2,так какDIV2является его родительским элементомbodyтретий дочерний элемент .
: фильтр n-го типа (n)
:nth-of-type(n)и:nth-child(n)Аналогично, за исключением того, что он представляет n-й элемент того же типа, поэтому:nth-of-type(1)и:first-of-typeРавно, можете попробовать сами, больше примеров здесь приводить не буду.
фильтры nth-last-child(n) и :nth-last-of-type(n)
Эти два аналогичны предыдущим, за исключением того, что расчет начинается в обратном порядке, и последний элемент рассматривается как первый. Давайте проверим и посмотрим на эффект, он очевиден.
: только дочерний фильтр
Find(":only-child")Фильтр, буквально, можно догадаться, он представляет собой фильтруемый элемент, в своем родительском элементе только он сам, его родительский элемент не имеет других дочерних элементов, будет сопоставлен и отфильтрован.
func main() {
html := `<body>
<div lang="zh">DIV1</div>
<span>
<div>DIV5</div>
</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div:only-child").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Html())
})
}
примерDIV5может быть отфильтрован, потому что это его родительский элементspanдостигает единственного дочернего элемента, ноDIV1Нет, так что это не может быть отфильтровано.
:фильтр только типа
В приведенном выше примере, если вы хотите отфильтровыватьDIV1что делать? можно использоватьFind(":only-of-type"), потому что это его родительский элемент, единственныйdivэлемент, это:only-of-typeЧто должен делать фильтр, пока есть только один элемент одного типа, его можно отфильтровать. Измените приведенный выше пример на:only-of-typeпопробуй, есть лиDIV1.
Выберите или (|) оператор
Если мы хотим отфильтровать обаdiv,spanА как насчет других элементов? В настоящее время можно использовать несколько селекторов в комбинации и разделять их запятыми (,).Find("selector1, selector2, selectorN")Указывает, что пока один из селекторов удовлетворяется, его можно отфильтровать, то есть выполнить операцию ИЛИ (|) селектора.
func main() {
html := `<body>
<div lang="zh">DIV1</div>
<span>
<div>DIV5</div>
</span>
</body>
`
dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html))
if err!=nil{
log.Fatalln(err)
}
dom.Find("div,span").Each(func(i int, selection *goquery.Selection) {
fmt.Println(selection.Html())
})
}
резюме
goquery — обязательный инструмент для анализа веб-страниц в формате HTML.В процессе сканирования веб-страниц гибкое использование различных селекторов goquery может сделать нашу работу по сканированию более эффективной и значительно повысить эффективность работы сканера.
Эта статья является оригинальной статьей, перепечатайте и укажите источник, добро пожаловать на сканирование кода и обратите внимание на общедоступный номер
flysnow_orgили сайтwww.flysnow.org/, и впервые прочитал последующие замечательные статьи. Если вы думаете, что это хорошо, пожалуйста, поделитесь им со своим кругом друзей, спасибо за вашу поддержку.