検索
ホームページウェブフロントエンドhtmlチュートリアルzhihu-go ソース コード分析: goquery を使用して HTML_html/css_WEB-ITnose を解析する

前回のブログでは zhihu-go プロジェクトの起源を簡単に紹介しましたが、この記事では HTML の処理の詳細を簡単に紹介します。

Zhihu は API を開発していないため、ブラウザーの操作をシミュレートすることによってのみデータを取得できます。データには、通常の HTML ドキュメントと、一部の Ajax インターフェイスによって返される JSON の 2 つの形式があります (返されるデータは実際には HTML です)。 )。実際には、これは Web ページを巡回してデータを抽出するクローラーです。一般に、HTML ドキュメントからデータを抽出するには、正規表現、XPath、CSS セレクターなどの方法があります。私にとって、正規表現は書くのがより複雑で、コードは読みにくく、保守も面倒です。XPath については詳しく知りませんが、使用するのは難しくないはずです。Chrome ブラウザは XPath を直接抽出できます。 selector は zhihu-go で使用されます。このメソッドは goquery を使用します。

goquery は「Go でのみ使用される j のものに少し似ています」、つまり、jQuery を使用して DOM を操作することを意味します。 API も非常にシンプルかつ明確です。この記事では goquery について詳しくは紹介しません。いくつかのシナリオ (API) を選択して、zhihu-go での goquery の応用について説明します。

Document オブジェクトの作成

goquery は、Document と Selection の 2 つの構造を公開します。Document は HTML ドキュメントを表し、Selection は jQuery のように動作するために使用され、チェーン呼び出しをサポートします。 goquery は、後続の操作を続行するために HTML ドキュメントを指定する必要があります。いくつかの構築メソッドがあります。

  • NewDocumentFromNode(root *html.Node) *Document: *html.Node オブジェクトを渡します。ルートノード。
  • NewDocument(url string) (*Document, error): URL を渡し、内部で http.Get を使用して Web ページを取得します。
  • NewDocumentFromReader(r io.Reader) (*Document, error): io.Reader を渡し、内部でリーダーからコンテンツを読み取り、解析します。
  • NewDocumentFromResponse(res *http.Response) (*Document, error): HTTP 応答を渡し、内部で res.Body を取得します (io.Reader を実装)。処理方法は NewDocumentFromReader
Zhihu ページにアクセスするにはログインが必要であり (リクエスト ヘッダーも偽造する必要がある)、*html.Node を取得するために HTML を手動で解析したくないため、最終的に他の 2 つの構築方法を使用しました。 。一般的な使用シナリオは次のとおりです。

    HTML ページ (質問ページなど) をリクエストし、NewDocumentFromResponse を呼び出します。
  • Ajax インターフェイスをリクエストします。返された JSON データにはいくつかの HTML フラグメントが含まれており、次のように使用します。 NewDocumentFromReader、r = strings.NewReader(html)
説明の便宜上、この定義は以下で使用されます: var doc *goquery.Document.

指定されたノードを検索します

Selection には jQuery に似た一連のメソッドがあります。 *Selection は Document 構造に埋め込まれているため、これらのメソッドを直接呼び出すこともできます。メインのメソッドは、Selection.Find(selector string) で、セレクターを渡して、一致する新しい *Selection を返すため、チェーン内で呼び出すことができます。

たとえば、ユーザーのホームページ (Huang Jixin など) では、まず Chrome を使用して、対応する HTML を見つけます。

<span class="bio" title="和知乎在一起">和知乎在一起</span>
対応する go コード。

doc.Find("span.bio")
セレクターが複数の結果に対応する場合、First()、Last()、Eq(index int)、Slice(start, end int) などのメソッドを使用してさらに位置を指定できます。

ユーザーのホームページでは、ユーザー情報欄の下に、質問、回答、記事、コレクション、公開編集の数が左から右に表示されます。 HTML ソース コードを確認したところ、これらの項目のクラスは同じであるため、添字インデックスによってのみ区別できることがわかりました。

最初に HTML ソース コードを確認します。

<div class="profile-navbar clearfix"><a class="item " href="/people/jixin/asks">提问<span class="num">1336</span></a><a class="item " href="/people/jixin/answers">回答<span class="num">785</span></a><a class="item " href="/people/jixin/posts">文章<span class="num">91</span></a><a class="item " href="/people/jixin/collections">收藏<span class="num">44</span></a><a class="item " href="/people/jixin/logs">公共编辑<span class="num">51648</span></a></div>
回答の数を見つけたい場合、対応する go コードは次のとおりです。

doc.Find("div.profile-navbar").Find("span.num").Eq(1)
属性操作

多くの場合、タグのコンテンツと特定の属性値を取得する必要がありますが、これは goquery を使用して簡単に行うことができます。

回答数を取得する上記の例を続けると、Text() 文字列メソッドを使用して、すべてのサブタグを含むタグ内のテキスト コンテンツを取得できます。

text := doc.Find("div.profile-navbar").Find("span.num").Eq(1).Text()    // "785"
Text() メソッドで返される文字列には前後に空白文字が多く含まれる場合がありますが、状況に応じて削除できます。

属性値を取得するのも簡単です。次の 2 つのメソッドがあります。

    Attr(attrName string) (val string, contains bool): 属性値と、属性が存在します。同様に、マップから値を取得します
  • AttrOr(attrName,defaultValue string) string: 前のメソッドと同様ですが、違いは、属性が存在しない場合、指定されたデフォルト値が返されることです
共通 使用シナリオは、a タグ付きのリンクを取得することです。上記の回答取得の例を続けて、ユーザー回答のホームページを取得したい場合は、次のようにすることができます:

href, _ := doc.Find("div.profile-navbar").Find("a.item").Eq(1).Attr("href")
属性を設定しクラスを操作する方法は他にもありますが、これについてはこれ以上説明しません。 。

反復

多くのシナリオでは、質問のフォロワーのリスト、すべての回答、回答に「いいね!」をしたユーザーのリストなど、リスト データを返す必要があります。この場合、一般に、同様のノードをすべて走査し、特定の操作を実行するには反復が必要です。

goquery には反復のための 3 つのメソッドが用意されており、いずれもパラメータとして匿名関数を受け入れます。
  • Each(f func(int, *Selection)) *Selection: 其中函数 f的第一个参数是当前的下标,第二个参数是当前的节点
  • EachWithBreak(f func(int, *Selection) bool) *Selection: 和 Each类似,增加了中途跳出循环的能力,当 f返回 false时结束迭代
  • Map(f func(int, *Selection) string) (result []string): f的参数与上面一样,返回一个 string 类型,最终返回 []string.

比如获取一个收藏夹(如 黄继新的收藏:关于知乎的思考)下所有的问题,可以这么做(见 zhihu-go/collections.go):

func getQuestionsFromDoc(doc *goquery.Document) []*Question {	questions := make([]*Question, 0, pageSize)	items := doc.Find("div#zh-list-answer-wrap").Find("h2.zm-item-title")	items.Each(func(index int, sel *goquery.Selection) {		a := sel.Find("a")		qTitle := strip(a.Text())		qHref, _ := a.Attr("href")		thisQuestion := NewQuestion(makeZhihuLink(qHref), qTitle)		questions = append(questions, thisQuestion)	})	return questions}

EachWithBreak在 zhihu-go 中也有用到,可以参见 Answer.GetVotersN 方法: zhihu-go/answer.go.

删除节点、插入 HTML、导出 HTML

有一个需求是把回答内容输出到 HTML,说白了其实就是修复和清洗 HTML,具体的细节可以看 answer.go 里的 answerSelectionToHtml 函数. 其中用到了一些需要修改文档的操作。

比如,调用 Remove()方法把一个节点删掉:

sel.Find("noscript").Each(func(_ int, tag *goquery.Selection) {    tag.Remove() // 把无用的 noscript 去掉})

在节点后插入一段 HTML:

sel.Find("img").Each(func(_ int, tag *goquery.Selection) {    var src string    if tag.HasClass("origin_image") {        src, _ = tag.Attr("data-original")    } else {        src, _ = tag.Attr("data-actualsrc")    }    tag.SetAttr("src", src)    if tag.Next().Size() == 0 {        tag.AfterHtml("<br>")   // 在 img 标签后插入一个换行    }})

在标签尾部 append 一段内容:

wrapper := `<html><head><meta charset="utf-8"></head><body></body></html>`doc, _ := goquery.NewDocumentFromReader(strings.NewReader(wrapper))doc.Find("body").AppendSelection(sel)

最终输出为 html 文档:

html, err := doc.Html()

总结

上面的例子基本涵盖了 zhihu-go 中关于 HTML 操作的场景,得益于 goquery 和 jQuery 的 API 风格,实现起来还是非常简单的。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
HTML:構造、CSS:スタイル、JavaScript:動作HTML:構造、CSS:スタイル、JavaScript:動作Apr 18, 2025 am 12:09 AM

Web開発におけるHTML、CSS、およびJavaScriptの役割は次のとおりです。1。HTMLは、Webページ構造を定義し、2。CSSはWebページスタイルを制御し、3。JavaScriptは動的な動作を追加します。一緒に、彼らは最新のウェブサイトのフレームワーク、美学、および相互作用を構築します。

HTMLの未来:ウェブデザインの進化とトレンドHTMLの未来:ウェブデザインの進化とトレンドApr 17, 2025 am 12:12 AM

HTMLの将来は、無限の可能性に満ちています。 1)新機能と標準には、より多くのセマンティックタグとWebComponentsの人気が含まれます。 2)Webデザインのトレンドは、レスポンシブでアクセス可能なデザインに向けて発展し続けます。 3)パフォーマンスの最適化により、応答性の高い画像読み込みと怠zyなロードテクノロジーを通じてユーザーエクスペリエンスが向上します。

HTML対CSS対JavaScript:比較概要HTML対CSS対JavaScript:比較概要Apr 16, 2025 am 12:04 AM

Web開発におけるHTML、CSS、およびJavaScriptの役割は次のとおりです。HTMLはコンテンツ構造を担当し、CSSはスタイルを担当し、JavaScriptは動的な動作を担当します。 1。HTMLは、セマンティクスを確保するためにタグを使用してWebページの構造とコンテンツを定義します。 2。CSSは、セレクターと属性を介してWebページスタイルを制御して、美しく読みやすくします。 3。JavaScriptは、動的でインタラクティブな関数を実現するために、スクリプトを通じてWebページの動作を制御します。

HTML:それはプログラミング言語か何か他のものですか?HTML:それはプログラミング言語か何か他のものですか?Apr 15, 2025 am 12:13 AM

htmlisnotaprogramminglanguage; itisamarkuplanguage.1)htmlStructuresandformatswebcontentusingtags.2)ItworkswithcsssssssssdjavascriptforInteractivity、強化を促進します。

HTML:Webページの構造の構築HTML:Webページの構造の構築Apr 14, 2025 am 12:14 AM

HTMLは、Webページ構造の構築の基礎です。 1。HTMLは、コンテンツ構造とセマンティクス、および使用などを定義します。タグ。 2. SEO効果を改善するために、などのセマンティックマーカーを提供します。 3.タグを介したユーザーの相互作用を実現するには、フォーム検証に注意してください。 4. JavaScriptと組み合わせて、動的効果を実現するなどの高度な要素を使用します。 5.一般的なエラーには、閉じられていないラベルと引用されていない属性値が含まれ、検証ツールが必要です。 6.最適化戦略には、HTTP要求の削減、HTMLの圧縮、セマンティックタグの使用などが含まれます。

テキストからウェブサイトへ:HTMLの力テキストからウェブサイトへ:HTMLの力Apr 13, 2025 am 12:07 AM

HTMLは、Webページを構築するために使用される言語であり、タグと属性を使用してWebページの構造とコンテンツを定義します。 1)htmlは、などのタグを介してドキュメント構造を整理します。 2)ブラウザはHTMLを分析してDOMを構築し、Webページをレンダリングします。 3)マルチメディア関数を強化するなど、HTML5の新機能。 4)一般的なエラーには、閉じられていないラベルと引用されていない属性値が含まれます。 5)最適化の提案には、セマンティックタグの使用とファイルサイズの削減が含まれます。

HTML、CSS、およびJavaScriptの理解:初心者向けガイドHTML、CSS、およびJavaScriptの理解:初心者向けガイドApr 12, 2025 am 12:02 AM

webdevelopmentReliesOnhtml、css、andjavascript:1)htmlStructuresContent、2)cssStylesit、および3)Javascriptaddsinteractivity、形成、

HTMLの役割:Webコンテンツの構造HTMLの役割:Webコンテンツの構造Apr 11, 2025 am 12:12 AM

HTMLの役割は、タグと属性を使用してWebページの構造とコンテンツを定義することです。 1。HTMLは、読みやすく理解しやすいようなタグを介してコンテンツを整理します。 2。アクセシビリティとSEOを強化するには、セマンティックタグなどを使用します。 3. HTMLコードの最適化により、Webページの読み込み速度とユーザーエクスペリエンスが向上する可能性があります。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール