Эта статья является оригинальной статьей, перепечатайте и укажите источник, добро пожаловать на сканирование кода и обратите внимание на общедоступный номер
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/, и впервые прочитал последующие замечательные статьи. Если вы думаете, что это хорошо, пожалуйста, поделитесь им со своим кругом друзей, спасибо за вашу поддержку.