golang goquery selector (селектор) пример Daquan

задняя часть Element HTML jQuery
golang goquery selector (селектор) пример Daquan

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

扫码关注