YiSpider: распределённая платформа для пауков
Введение
YiSpider — это распределённая платформа, которая помогает лучше управлять и разрабатывать пауков. Она включает в себя набор правил определения пауков (шаблоны), которые можно использовать для быстрого создания пауков или в качестве фреймворка для ручного создания пауков.
План
Архитектура
В настоящее время фреймворк состоит из двух частей:
Внутренняя структура основана на Python Scrapy, в основном состоит из schedule, page process, pipline четырёх частей, каждый паук имеет отдельный планировщик, отдельное управление контекстом, в настоящее время встроено два способа pipline, вывод на консоль и файл, информация об узле зарегистрирована в etcd для управления обнаружением узлов.
core
: отвечает за жизненный цикл паука и управление контекстом, отвечает за выполнение паука.schedule
: отвечает за планирование запросов паука. (на основе channel или redis планировщика)process
: отвечает за обработку результатов запроса.pipline
: результаты выводятся в различные каналы, такие как консоль, файлы, очереди сообщений, базы данных и т. д.register
: отвечает за регистрацию сервисов (в настоящее время поддерживается только etcd).http
: предоставляет некоторые HTTP-интерфейсы.Отвечает за управление узлами пауков, использует etcd для обнаружения узлов пауков через HTTP.
Начало работы
В пакете example-spider есть множество примеров:
Существует два синтаксиса URL для начального запроса (Request), которые используются для удобства:
start = 0 20 40 ... 10000
url = https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={0-10000,20}
start = 0 20 40 60
url = https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={0|20|40|60}
Если href = "/abc" (href — это параметр, проанализированный процессом)
url = http://www.dilidili.wang{$href}
url = http://www.dilidili.wang/abc
url = https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={0-$count,20}
и так далее
Примеры
HTTP-вызов интерфейса
curl -d '{"id":"douban-movie","Name":"douban-movie","request":[{"url":"https://movie.douban.com/j/new_search_subjects?sort=T\u0026range=0,10\u0026tags=\u0026start={0-100,20}","method":"get","type":"","data":null,"header":null,"cookies":{"url":"","data":""},"process_name":"movie"}],"process":[{"name":"movie","reg_url":null,"type":"json","template_rule":{"Rule":null},"json_rule":{"Rule":{"casts":"casts","cover":"cover","id":"id","node":"array|data","rate":"rate","star":"star","title":"title","url":"url"}},"add_queue":null}],"pipline":"file","depth":0,"end_count":0}' "http://127.0.0.1:7774/task/addAndRun"
Пример шаблона Douban Movie:
{
"id": "douban-movie",
"Name": "douban-movie",
"request": [
{
"url": "https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={0-10,20}",
"method": "get",
"process_name": "movie"
}
],
"process": [
{
"name": "movie",
"type": "json",
"json_rule": {
"Rule": {
"casts": "casts",
"cover": "cover",
"id": "id",
"node": "array|data",
"rate": "rate",
"star": "star",
"title": "title",
"url": "url"
}
},
"add_queue": null
}
],
"pipline": "file",
"depth": 0,
"end_count": 0
}
Пример Dilidili:
{
"id": "dilidili",
"Name": "dilidili",
"request": [
{
"url": "http://www.dilidili.wang/{gaoxiao|kehuan|yundong|danmei|zhiyuxi|luoli|zhenren|zhuangbi|youxi|tuili|qingchun|kongbu|jizhan|rexue|qingxiaoshuo|maoxian|hougong|qihuan|tongnian|lianai|meishaonv|lizhi|baihe|paomianfan|yinv}/",
"method": "get",
"process_name": "animelist"
}
],
"process": [
{
"name": "animelist",
"type": "template",
"template_rule": {
"Rule": {
"content": "text|dd div",
"desc": "text|dd p",
"href": "attr.href|dt a",
"img": "attr.src|dt a img",
"node": "array|.anime_list dl",
"title": "text|dd h3 a"
}
},
"add_queue": [
{
"url": "http://www.dilidili.wang{href}",
"method": "get",
"process_name": "animeinfo"
}
]
},
{
"name": "animeinfo",
"type": "template", **Текст запроса:**
template_rule: { Rule: { episode: "texts|.time_con .swiper-slide .clear li a em", episode-link: "attrs.href|.time_con .swiper-slide .clear li a", title: "text|.detail dl dd h1" } }, add_queue: [ { url: "{episode-link}", method: "get", process_name: "episodeinfo" } ] }, { name: "episodeinfo", reg_url: null, type: "template", template_rule: { Rule: { player: "attr.src|.player_main iframe", title: "text|#intro2 h1", url: "attr.href|link[rel="canonical"]" } }, add_queue: null } ], pipline: "file", depth: 0, end_count: 0
**Перевод:**
template_rule: { Правило: { эпизод: «тексты|.time_кон .swiper-слайд .чистый ли а эм», ссылка на эпизод: «атрибуты.href|.time_кон .swiper-слайд .чистый ли a», название: «текст|.деталь дл дд h1» } }, добавить в очередь: [ { URL: «{ссылка на эпизод}», метод: «получить», имя процесса: «информация об эпизоде» } ] }, { имя: «информация об эпизоде», рег_URL: ноль, тип: «шаблон», template_rule: { Правило: { игрок: «атрибут.src|.player_главный iframe», название: «текст|#intro2 h1», URL: «атрибут.href|ссылка[rel = "канонический"]» } }, добавить в очередь: ноль } ], трубопровод: «файл», глубина: 0, конечное количество: 0
AddQueue:[]*model.Request{
{
Method: "get",
Url: "{$episode-link}",
ProcessName: "episodeinfo",
},
},
{
Name:"episodeinfo",
Type:"template",
TemplateRule:model.TemplateRule{
Rule:map[string]string{
"url":"attr.href|link[rel=\"canonical\"]",
"title":"text|#intro2 h1",
"player":"attr.src|.player_main iframe",
},
},
},
},
Pipline:"file",
}
app := spider.New()
app.AddSpider(spider2.InitWithTask(task))
app.Run()
**Перевод текста запроса 1 на русский язык:**
AddQueue: [] * model.Request { { Метод: «get», URL: «{$episode-link}», Имя процесса: «episodeinfo», }, }, { Имя: «episodeinfo», Тип: «template», Правило шаблона: model.TemplateRule { Правило: map[строка] строка { «url»: «attr.href | link [rel = „canonical“]», «title»: «text | # intro2 h1», «player»: «attr.src | .player_main iframe», }, }, }, }, Pipeline: «file», }
app: = spider.New () app.AddSpider (spider2.InitWithTask (задача)) app.Run ()
**Текст запроса 2:**
type Movies struct {
Datas []Movie `json:"data"`
}
type Movie struct {
Rate string `json:"rate"`
Start string `json:"start"`
Id string `json:"id"`
Url string `json:"url"`
Title string `json:"title"`
Cover string `json:"cover"`
Casts []string `json:"casts"`
}
type PageProcess struct{}
func (p *PageProcess) Process(context model.Context) (*model.Page, error) {
movies := Movies{}
if err := json.Unmarshal(context.Body, &movies); err != nil {
return nil, err
}
page := &model.Page{}
for _, movie := range movies.Datas {
page.AddResult(movie)
}
return page, nil
}
func main() {
sp := &spider2.Spider{}
sp.Name = "douban-movie-code"
sp.Id = "douban-movie-code"
sp.Requests = []*model.Request{
{
Method: "get",
Url: "https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={0-10000,20}",
ProcessName: "movie",
},
}
sp.AddProcess("movie", &PageProcess{})
sp.Pipline = file.NewFilePipline("./")
app := spider.New()
app.AddSpider(sp)
app.Run()
}
**Перевод текста запроса 2 на русский язык:**
type Movies struct {
Datas []Movie json:"data"
}
type Movie struct {
Rate string json:"rate"
,
Start string json:"start"
,
Id string json:"id"
,
Url string json:"url"
,
Title string json:"title"
,
Cover string json:"cover"
,
Casts []string json:"casts"
,
}
type PageProcess struct {}
func (p *PageProcess) Process(context model.Context) (*model.Page, error) { movies := Movies{} if err := json.Unmarshal(context.Body, &movies); err != nil { return nil, err } page := &model.Page{} for _, movie := range movies.Datas { page.AddResult(movie) } return page, nil }
func main() { sp := &spider2.Spider{} sp.Name = "douban-movie-code" sp.Id = "douban-movie-code" sp.Requests = []*model.Request{ { Метод: "get", URL: "https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start={0-10000,20}", Имя процесса: "movie", }, } sp.AddProcess("movie", &PageProcess{}) sp.Pipeline = file.NewFilePipeline("./")
app := spider.New()
app.AddSpider(sp)
app.Run()
}
Примечание: В запросе 2 есть код на языке Go. Я не могу гарантировать, что перевод кода на русский язык будет точным и корректным.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )