Быстро начните работу с Go и просмотрите колонку Nuggets | 🏆 Технический специальный выпуск 2

Go
Быстро начните работу с Go и просмотрите колонку Nuggets | 🏆 Технический специальный выпуск 2

Перейти показы

Однажды в 2018 году я спросил бэкенд-архитектора компании, что хочу выучить язык бэкенда, кроме Java, он сказал мне, что изучает Go. Затем он рассказал мне о некоторых понятиях, таких как распределение, сопрограммы, большие данные, рептилии... понятия Барабалы, которые я не совсем понимаю. Тогда я сказал, что мне лучше изучить NodeJs.

Причина, по которой она снова осмелилась бороться с языком го, полностью связана с Лян Цзинру (последний призыв к бумагам) придало мне смелости. Если вы являетесь бэкэнд-боссом, просто прочитайте гусеничную часть второй половины.

Тема этой статьи — скорость, поисковые роботы и колонка Nuggets. Цель — использовать Go для написания небольшого инструмента, который будет сканировать колонку Nuggets и медленно читать ее.

Let's Go

Преимущество

  • Простая грамматика и простота использования (всего 25 зарезервированных ключевых слов)
  • Высокая производительность, быстрая компиляция и эффективность разработки не ниже Python и Ruby.
  • Его легко развернуть, пакет компиляции небольшой, и почти нет зависимостей (пакет бинарных файлов можно запускать напрямую), что очень похоже на Deno.
  • Встроенная поддержка параллелизма (горутина)
  • Официальная унифицированная спецификация (gofmt, golint) снова увидела тень Deno
  • Богатая стандартная библиотека, снова увидеть тень Deno

тренд

Авторитетный тренд, ваш дуговой босс, уже ясно дал понять, я добавлю сюда звездный тренд GitHub:

Введение в Го

Go — статически строго типизированный, скомпилированный параллельный язык программирования с функцией сборки мусора, разработанный Google. Иногда его называют Golang для простоты поиска и идентификации.

Особенности языка Go

  1. Go — это новый язык, статический язык, который поддерживает параллелизм, сборку мусора и быструю компиляцию.
  2. Go обеспечивает базовую поддержку параллельного выполнения и обмена данными и является естественным высокопроизводительным языком разработки сервисов.
  3. Go сочетает в себе простоту интерпретируемого языка, эффективность разработки языка с динамической типизацией и безопасность статической типизации.
  4. Go может скомпилировать большую программу Go за считанные секунды, а развертывание очень простое.
  5. Go обладает эффективностью разработки Python/Ruby и производительностью языка C (все еще существует определенный разрыв).
  6. Go легко выучить (всего 25 ключевых зарезервированных слов)
  7. Go имеет собственную спецификацию разработки, а также предоставляет инструментальную поддержку.

Перейти к настройке установки

у автора другаяСреда разработки программиста для Mac [постоянно обновляется], записал среду разработки на свой Mac, может кстати читатели дадут звезду?

$ brew install go

Совет 1:ctrl+cможно пропуститьUpdating Homebrew..., иначе вы застрянете и будете сомневаться в своей жизни.

Совет 2: Если у вас есть время ждать, возьмите его с собой-verboseпараметры, так что загрузка будет сообщать вам о ходе обновления.

Совет 3: Homebrew — это синхронизированный репозиторий GitHub.Если вы застряли, измените источник прокси-сервера Homebrew самостоятельно.

После успешной установки проверьте версию go:

$ go version
go version go1.14.7 darwin/amd64

Настройте переменные среды:

$ open /usr/local/Cellar/go/

Затем посмотрите, где находится ваш libexec, и запишите общий адрес./usr/local/Cellar/go/1.14.7/libexec

Эту часть нужно записатьnano ~/.zshrc:

#GO
export GOROOT=/usr/local/Cellar/go/1.14.7/libexec
export GOPATH=~/.go
export PATH=${PATH}:$GOPATH/bin

не забудьте выполнить source ~/.zshrcвступит в силу после команды. затем выполнитьgo envПроверьте, успешно ли выполнена команда

Вывод слишком длинный, пожалуйста, нажмите, чтобы просмотреть! ! !
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/yangjunning/Library/Caches/go-build"
GOENV="/Users/yangjunning/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/yangjunning/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/local/Cellar/go/1.14.7/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.14.7/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/zn/17xnqr8s1pjbpzt9_t38tyhc0000gn/T/go-build998676802=/tmp/go-build -gno-record-gcc-switches -fno-common"

Прокси-сервер Qiniu Cloud Mirror

Откройте свой терминал и выполните, Go 1.13 и выше возможны, другие версии, пожалуйста, прочитайтеGoproxy КитайПосмотреть документацию

$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct

Перейти общие команды

1,go build: используется для компиляции исходных файлов или пакетов кода, которые мы указываем, и их зависимостей.

2,go clean: используется для удаления скомпилированных файлов в текущем исходном пакете

3.go doc: Распечатайте документацию, прикрепленную к программному объекту языка Go. Мы можем просмотреть его документацию, передав идентификатор программного объекта в качестве аргумента этой команде.

4.go fmt: помогите отформатировать ваши файлы кода, вам просто нужно выполнить go fmt xxx.go ваш код будет изменен в стандартный формат

5.go get: Загрузите или обновите указанные пакеты зависимостей на уровне кода из Интернета в соответствии с требованиями и фактическими условиями, а затем скомпилируйте и установите их.

6.go install: используется для компиляции и установки указанных пакетов кода и их зависимостей.

7.go run: вы можете просмотреть исходный код и запустить исходный файл команды.

Стандартная библиотека Go

1. sync: Предоставляет базовые примитивы синхронизации. Когда несколько горутин получают доступ к общим ресурсам, необходимо использовать синхронизированный механизм блокировки.

2. os: предоставляет не связанные с платформой интерфейсы доступа к функциям операционной системы. Интерфейс выполнен в стиле Unix. Предоставляемые функции включают операции с файлами, управление процессами, сигналы и учетные записи пользователей.

3, время: обработка, связанная со временем

4. fmt: реализация форматированных операций ввода и вывода.

5. io: реализует ряд не связанных с платформой интерфейсов ввода-вывода и реализаций, таких как обеспечение инкапсуляции системных функций ввода-вывода в os. Этот пакет используется, когда мы выполняем потоковое чтение и запись (например, чтение и запись файлов).

6. http: предоставление веб-сервисов

7. строка: набор функций для обработки строк, включая слияние, поиск, разделение, сравнение, проверку суффиксов, индексирование, обработку регистра и многое другое.

Рекомендация плагина VsCode

  • Go: расширенная поддержка языка Go для Visual Studio Code.

Hello World

Создайтеhelloworld.goНапишите следующее:

package main  // 代码包声明语句。
import "fmt" // 系统包用来输出的

func main() {
  // 打印函数调用语句。用于打印输出信息。
  fmt.Println(sayHello("掘金"))
}

func sayHello(juejin string) string {
  return "Hello "+juejin
}

затем выполнитьgo run helloworld.go, Хорошо, вы уже начали. Теперь вы можете начать изучение краулера вместе. Далее я покажу вам шаг за шагом, чтобы реализовать сканирующий столбец самородков и преобразовать его в формат Markdown и сохранить его в небольшой краулер локально, с именем Этоjuejin-spider.

что такое рептилия

Определение поискового робота в энциклопедии Baidu и Википедии: Проще говоря, поисковый робот — это инструмент для сканирования содержимого целевого веб-сайта.Как правило, он автоматически выполняет сканирование в соответствии с определенным поведением, анализирует и фильтрует веб-страницу или данные; стратегия сканирования.

Проще говоря, нужно загрузить целевую веб-страницу, а затем получить нужные данные с помощью ряда операций, таких как синтаксический анализ, фильтрация и дедупликация, и сохранить их в соответствующем формате. Общий процесс выглядит следующим образом:

Коллой быстро заводится

gocolly — это фреймворк для поиска в Интернете, реализованный с помощью go. gocolly быстр и элегантен и может инициировать более 1000 запросов в секунду на одном ядре; он предоставляет набор интерфейсов в виде функций обратного вызова, которые могут реализовать любой тип сканера; опираясь на библиотеку goquery, можно выбирать веб-элементы как jquery.

Официальный сайт gocollygo-colly.org/, который содержит подробную документацию и пример кода. Установить колли:

$ go get -u github.com/gocolly/colly/...

Первая рептилия в жизни

существуетgo.modУправление зависимостями в:

module juejin.im/junning

go 1.14

require (
  github.com/gocolly/colly/v2 latest
)

новыйmain.goфайл и напишите код:

Этот код не длинный, но я прочитал официальную документацию и пять или шесть блогов, прежде чем я его сделал, просто чтобы сделать первый краулер в моей жизни достаточно полным.

package main

import (
	"fmt"
	// 1、导入 colly。
	"github.com/gocolly/colly"
	"github.com/gocolly/colly/extensions"
)

func main() {
	// 2、创建 collector
	c := colly.NewCollector(colly.AllowedDomains("juejin.im")) // 要限定域名,否则就把全网都爬下来了
	extensions.RandomUserAgent(c)                              // 使用随机的UserAgent,最好能使用代理。这样就不容易被ban
	extensions.Referer(c)                                      // 在访问的时候带上Referrer,意思就是这一次点击是从哪个页面产生的

	// 3、事件监听,通过 callback 执行事件处理。
	c.OnError(func(_ *colly.Response, err error) {
		fmt.Println("Something went wrong:", err)
	})
	c.OnRequest(func(r *colly.Request) {
		// fmt.Println("Visiting", r.URL)
	})
	// Find and visit all links
	c.OnHTML("a[href]", func(e *colly.HTMLElement) {
		fmt.Println(e.Text)
		e.Request.Visit(e.Attr("href"))
	})

	// 4、启动网页访问
	c.Visit("https://juejin.cn")
}

Обратные вызовы и порядок их вызова

Принцип gocolly заключается в отслеживании доступа к сети и предоставлении разработчикам 7 событий и обратных вызовов.

  1. OnRequest: вызывается перед выполнением запроса
  2. OnError: вызывается при сбое запроса
  3. OnResponseHeaders: вызывается после получения заголовков ответа, вызывается при получении заголовков ответа.
  4. OnResponse: вызывается, когда ответ завершен
  5. OnHTML: вызывается сразу после OnResponse, если полученный контент является HTML
  6. OnXML: вызывается сразу после OnHTML, если полученное содержимое является HTML или XML.
  7. OnScraped: вызывается сразу после OnXML

определение типа

перечислено здесь*colly.HTMLElementи*colly.RequestОпределение типа в процессе разработки, вы можете в любое время перейти к файлу определения типа или просмотретьGitHub.com/go колл Y/кол…Соответствующие файлы в можно (говорят, что исходники очень хорошо написаны, и у меня есть время их изучить). PS: На самом деле у TypeScript есть много общего, которое можно изучить по аналогии, поэтому я могу начать работу за одну ночь.

*colly.HTMLElement

Онлайн ссылка:GitHub.com/go колл Y/кол…

// HTMLElement is the representation of a HTML tag.
type HTMLElement struct {
	// Name is the name of the tag
	Name       string
	Text       string
	attributes []html.Attribute
	// Request is the request object of the element's HTML document
	Request *Request
	// Response is the Response object of the element's HTML document
	Response *Response
	// DOM is the goquery parsed DOM object of the page. DOM is relative
	// to the current HTMLElement
	DOM *goquery.Selection
	// Index stores the position of the current element within all the elements matched by an OnHTML callback
	Index int
}

*colly.Request

Онлайн ссылка:GitHub.com/go колл Y/кол…

// Request is the representation of a HTTP request made by a Collector
type Request struct {
	// URL is the parsed URL of the HTTP request
	URL *url.URL
	// Headers contains the Request's HTTP headers
	Headers *http.Header
	// Ctx is a context between a Request and a Response
	Ctx *Context
	// Depth is the number of the parents of the request
	Depth int
	// Method is the HTTP method of the request
	Method string
	// Body is the request body which is used on POST/PUT requests
	Body io.Reader
	// ResponseCharacterencoding is the character encoding of the response body.
	// Leave it blank to allow automatic character encoding of the response body.
	// It is empty by default and it can be set in OnRequest callback.
	ResponseCharacterEncoding string
	// ID is the Unique identifier of the request
	ID        uint32
	collector *Collector
	abort     bool
	baseURL   *url.URL
	// ProxyURL is the proxy address that handles the request
	ProxyURL string
}

Сканировать колонку Nuggets

Принцип действия поискового робота заключается в имитации доступа к веб-странице, получении информации о документе, преобразовании информации в необходимые данные с помощью различных средств и сохранении данных.

Поскольку автор спешит начать работу с языком Go за одну ночь и не может реализовать краулер для сканирования данных, я реализовал следующее:

访问掘金专栏详情页
		⏬
获取指定的内容和标题部分
		⏬
将标题作为文件名
		⏬
把内容转为Markdown格式存入文件
		⏬
保存文件到本地

Анализировать структуру страницы

Структура заголовка столбца

<h1 data-v-23a9d5ed="" class="article-title">(.*?)<\/h1>

Структура корпуса колонны

<div class="markdown-body">(.*?)<\/div>

Получить заголовок и содержимое столбца

func main() {
	c := colly.NewCollector(
		colly.Async(true),
	)

	c.OnRequest(func(r *colly.Request) {
		fmt.Println("Visiting", r.URL)
	})

	c.OnError(func(_ *colly.Response, err error) {
		log.Println("Something went wrong:", err)
	})

	c.OnHTML(".article-title", func(e *colly.HTMLElement) {
		// Code Here
	})

	c.OnHTML(".markdown-body", func(e *colly.HTMLElement) {
		// Code Here
	})

	c.Visit("https://juejin.im/post/" + *post)
	c.Wait()
}
  • colly.NewCollectorдобавил одинcolly.Async(true), что означает, что выборка является асинхронной, что может значительно повысить скорость выборки.
  • использоватьOnHTMLСобытия захватываются отдельно с помощьюarticle-titleи.markdown-bodyЭлемент, который является местом реализации логики функции, которую мы хотим реализовать ниже.
  • OnHTMLПервый параметр соответствует правилам селектора CSS, вы можете использовать любой селектор, чтобы что-то делать.

Конвертировать HTML в Markdown

Здесь мы используемhtml-to-markdownФункции, предоставляемые этой библиотекой, мы просто инкапсулируем в ней:

// 将Html转为Markdown
func convertHTMLToMarkdown(selection *goquery.Selection) string {
	converter := md.NewConverter("", true, nil)
	markdown := converter.Convert(selection)
	return markdown
}

сохранить файл на локальном

...
// 写入文件
func writeFile(fileName string,content string) {
	filePath := fileName + ".md"
	var file *os.File

	if checkFileIsExist(filePath) {
		// 如果文件存在,则删除
		err := os.Remove(filePath)
		if err != nil {
			log.Fatal(err)
		}
	}

	// 创建文件并写入内容
	file, _ = os.Create(filePath)
	n, _ := io.WriteString(file, "## "+fileName+"\n\n"+content)
	// 关闭文件
	file.Close()
	if n == 0 {
		return
	}
}

// 检查文件是否存在
func checkFileIsExist(fileName string) bool {
	_, err := os.Stat(fileName)
	if err != nil {
		return false
	}
	return true
}
...
  • os.Stat: используется для получения информации о файле или файле, на основе которой он инкапсулируетcheckFileIsExistПроверьте, существует ли файл
  • os.Create+io.WriteStringРеализовано создание файлов и запись в файлы
  • Чтобы определить, существует ли файл, используйтеos.Remove(filePath)Удалите файл, чтобы перезаписать файл (лень смотреть метод перезаписывания файла)

Получить аргументы командной строки

Этот метод написания подобен, когда я использую NodeJS для написания инструментов CLI.Если вам интересно, вы можетепосмотри,Не обязательно в следующий раз, только в этот раз.

func main() {
	var post = flag.String("post", "6859538537830858759", "文章编号")
	var rootDir = flag.String("root", root, "文件保存的根目录")
  flag.Parse()
}

получить переменные окружения

Использование не поддерживается на языке GO~Число представляет собой домашний каталог.После долгих метаний я нашел это решение.Это не то же самое, что и Deno.Этот языковой дизайн заимствован (копирован) друг у друга.

os.Getenv("HOME")

получить фотографии

При тестировании скрипта я обнаружил что статьи с картинками пропали.Как это может работать?Статьи без картинок не имеют души. Результат анализа — изображение Наггетса загружается лениво, а метка выглядит так:

<img class="lazyload inited loaded" data-src="https://i.loli.net/2020/08/13/cVomW7L9YOTw2uA.png" data-width="800" data-height="600" src="https://i.loli.net/2020/08/13/cVomW7L9YOTw2uA.png">

Я думаю, этоdata-проблема с атрибутами, поэтому я добавил в скрипт следующий код, чтобыdata-Удалить:

...
reg := regexp.MustCompile(`data-`)
		html, _ := e.DOM.Html()
		markdown := convertHTMLToMarkdown(reg.ReplaceAllString(html, ""))
...

youngjuning/homebrew-juejin-spider@0.1.0Он был выпущен, и он может отлично захватить колонку Nuggets.

готовый продукт

Код слишком длинный, исходный код здесь 》》》На GitHub.com/ есть этот гигантский нин..."", я все это прочитал здесь, поставьте мне звезду.

Упакуйте и опубликуйте скрипт с помощью Homebrew

Хакеров надо преследовать, из игрушки сделать невозможно. А сам Go работает без каких-либо зависимостей и окружений, я не могу просить людей, использующих инструменты, установить go-окружение. Моей первой мыслью было отправить мой скрипт в Homebrew, слава богу,Публикация скриптов с помощью HomeBrewЭтот процесс подробно описан.

1. Упакуйте его в исполняемый файл

$ go build juejin.go

В текущем каталоге будет сгенерирован исполняемый файл с именем juejin,./juejinявляется исполняемым, вы также можете использоватьgo build -o=/usr/local/bin juejin.goилиgo build -o=$GOPATH/bin/ juejin.goв зарегистрированный системный путь.

2. Упаковать исполняемый файл в формат tar.gz

$ tar zcvf juejin_0.0.1.tar.gz juejin

Загрузите в git рецепт для символической ссылки на этот файл скрипта.

3. Используйтеbrew create <git-url> --tab user/repoСоздать рецепт

$ brew create \
    https://github.com/youngjuning/homebrew-juejin-spider/raw/master/juejin_0.0.1.tar.gz \
    --tap youngjuning/homebrew-juejin-spider

Нам нужно внести некоторые коррективы в метод установки:

def install
    bin.install "juejin"
end

После выполнения этих операций сохраните и отправьте в git.

4. Скрипт установки

$ brew install youngjuning/juejin-spider/juejin

воплощать в жизньjuejin -hПроверить на успех:

$ juejin -h
Usage of juejin:
  -post string
    	文章编号 (default "6859538537830858759")
  -root string
    	文件保存的根目录 (default "/Users/yangjunning/juejin")

Устанавливайте собственные скрипты на чужие устройства

// 在执行这个命令的时候,brew会自动去更新自己的formula仓库,会耗时几分钟。。。
$ brew tap youngjuning/juejin-spider https://github.com/youngjuning/homebrew-juejin-spider.git
// 下载、安装脚本
$ brew install youngjuning/juejin-spider/juejin

супер сайян город

Спасибо, что терпеливо читаете эту статью. Нравится — значит учится, коллекции — это мастерство, а лайки и коллекции — это настоящая любовь! ! ! С нетерпением жду обсуждения со мной в разделе комментариев! ! !

🏆 Технический спецвыпуск 2 | То, что я сделал с Go...