如何使用生成器抓取页面内容?
How do I scrape page content with a generator?
我有一个博客,每个 post 都有一堆图片和视频。我希望能够用一些关键字标记它们中的每一个,然后根据标记填充一组页面。例如转到 /photos/car/
将列出所有标记为 car
.
的图像
我现在使用一个简单的插件来包含图像和视频,该插件基本上只有渲染功能。我想我可以在那里添加标签。
但是我怎样才能使 Jekyll 'scrape' 我的页面并用图像填充页面?
简短的回答是:这很棘手。
但是为什么呢?
像 {% img cookie-monster.png tag2,tag3 %}
这样的自定义 imgWithTags-tag
液体标签可以做两件事:
- 渲染 html 标签
- 存储标签 ->
site.taggedImage
变量中的图像关联
由于此标记可用于任何 post、页面或集合文档,因此 site.taggedImage
变量仅在呈现过程后才完整。
渲染过程完成后,我们可以获取 :site, :post_render
挂钩来处理我们的数据并创建标签页面。
但是在这里,我们不能再依赖诸如 {% for p in tagPages %}...{% endfor %} 之类的东西来自动为我们的页面生成 links:渲染完成。
诀窍可以是手动维护一个 link 数据文件,以便能够生成 link 具有像这样的循环 {% for p in site.data.tagPages %}...{% endfor %}
让我们试一试
注意:这仅适用于 Jekyll 版本 3.1.x(不是 3.0.x)
_plugins/imgWithTags-tag.rb
module Jekyll
class ImgWithTags < Liquid::Tag
# Custom liquid tag for images with tags
# syntax : {% img path/to/img.jpg coma, separated, tags %}
# tags are optionnal
#
# This plugin does two things :
# it renders html tag <a href='url'><img src='url' /></a>
# it stores tags -> images associations in site.config['images-tags']
Syntax = /^(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<tags>[\s\S]+)?$/
def initialize(tag_name, markup, tokens)
super
if markup =~ Syntax then
@url =
@tags = .split(",").collect!{|tag| tag.strip } if !.nil?
else
raise "Image Tag can't read this tag. Try {% img path/to/img.jpg [coma, separated, tags] %}."
end
end
def render(context)
storeImgTags(context) if defined?(@tags) # store datas if we have tags
site = context.registers[:site]
imgTag = "<a href='#{ site.baseurl }/assets/#{@url}'><img src='#{ site.baseurl }/assets/#{@url}' /></a>"
end
def storeImgTags(context)
# store tagged images datas in site config under the key site.config['images-tags']
imagesTags = context.registers[:site].config['images-tags'] || {}
@tags.each{|tag|
slug = Utils.slugify(tag) # My tag -> my-tag
# create a tag.slug entry if it doesn't exist
imagesTags[slug] = imagesTags[slug] || {'name' => tag, 'images' => [] }
# add image url in the tag.images array if the url doesn't already exist
# this avoid duplicates
imagesTags[slug]['images'] |= [@url.to_s]
}
context.registers[:site].config['images-tags'] = imagesTags
end
end
end
Liquid::Template.register_tag('img', Jekyll::ImgWithTags)
此时:所有标记图像 link 均已呈现,所有标记->图像关联已存储。
_plugins/hook-site-post-render-imagesTagsPagesGenerator.rb
Jekyll::Hooks.register :site, :post_render do |site, payload|
puts "++++++ site post_render hook : generating Images Tags pages"
imagesTags = site.config['images-tags'] # datas stored by img tag
linksDatas = site.data['imagesTagsLinks'] # tags pages link in data file
pagesFolder = 'tag'
imagesTags.each do |slug, datas|
tagName = datas['name']
tagImages = datas['images']
pageDir = File.join(pagesFolder, slug)
tagPage = Jekyll::ImageTagPage.new(site, site.source, pageDir, tagName, tagImages)
# as page rendering has already fired we do it again for our new pages
tagPage.output = Jekyll::Renderer.new(site, tagPage, payload).run
tagPage.trigger_hooks(:post_render)
site.pages << tagPage
# verbose check to see if we reference every tag url in out data file
if !linksDatas.key?(tagName) # check if tag is in imagesTagsLinks data file
puts "Warning ---------> #{tagName} not in data file"
puts "Add : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
else
if tagPage.url != linksDatas[tagName] then # check if url is correct in imagesTagsLinks data file
puts "Warning ---------> incorrect url for '#{tagName}'"
puts "Replace : #{tagName}: #{linksDatas[tagName]}"
puts "by : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
end
end
end
puts "++++++ END site post_render hook"
end
module Jekyll
class ImageTagPage < Page
def initialize(site, base, dir, tag, images)
@site = site
@base = base
@dir = dir
@name = 'index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'tag_index.html')
self.data['tag'] = tag
self.data['images'] = images
self.data['title'] = "Images for tag : #{tag}"
end
end
end
以及标签布局页面
_layouts/tag_index.html
---
layout: default
---
<h2>{{ page.title }}</h2>
{% for i in page.images %}
<img src="{{ site.baseurl }}/assets/{{ i }}" alt="Image tagged {{ page.tag }}">
{% endfor %}
至此,生成标签页面的一切就绪。
我们现在可以执行 jekyll build
并查看详细输出,告诉我们要在 _data/imagesTagsLinks.yml
中添加什么
_数据/imagesTagsLinks.yml
tag1: /tag/tag1/
tag2: /tag/tag2/
...
我们现在可以 link 从任何地方通过一个简单的
到我们的标签页
{% for t in site.data.imagesTagsLinks %}
<li><a href="{{ site.baseurl }}{{ t[1] }}">{{ t[0] }}</a></li>
{% endfor %}
我告诉过你:这很棘手。但它完成了工作。
注意:img
标签可以改进,为什么 figure
标签不行?
我有一个博客,每个 post 都有一堆图片和视频。我希望能够用一些关键字标记它们中的每一个,然后根据标记填充一组页面。例如转到 /photos/car/
将列出所有标记为 car
.
我现在使用一个简单的插件来包含图像和视频,该插件基本上只有渲染功能。我想我可以在那里添加标签。
但是我怎样才能使 Jekyll 'scrape' 我的页面并用图像填充页面?
简短的回答是:这很棘手。
但是为什么呢?
像 {% img cookie-monster.png tag2,tag3 %}
这样的自定义 imgWithTags-tag
液体标签可以做两件事:
- 渲染 html 标签
- 存储标签 ->
site.taggedImage
变量中的图像关联
由于此标记可用于任何 post、页面或集合文档,因此 site.taggedImage
变量仅在呈现过程后才完整。
渲染过程完成后,我们可以获取 :site, :post_render
挂钩来处理我们的数据并创建标签页面。
但是在这里,我们不能再依赖诸如 {% for p in tagPages %}...{% endfor %} 之类的东西来自动为我们的页面生成 links:渲染完成。
诀窍可以是手动维护一个 link 数据文件,以便能够生成 link 具有像这样的循环 {% for p in site.data.tagPages %}...{% endfor %}
让我们试一试
注意:这仅适用于 Jekyll 版本 3.1.x(不是 3.0.x)
_plugins/imgWithTags-tag.rb
module Jekyll
class ImgWithTags < Liquid::Tag
# Custom liquid tag for images with tags
# syntax : {% img path/to/img.jpg coma, separated, tags %}
# tags are optionnal
#
# This plugin does two things :
# it renders html tag <a href='url'><img src='url' /></a>
# it stores tags -> images associations in site.config['images-tags']
Syntax = /^(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<tags>[\s\S]+)?$/
def initialize(tag_name, markup, tokens)
super
if markup =~ Syntax then
@url =
@tags = .split(",").collect!{|tag| tag.strip } if !.nil?
else
raise "Image Tag can't read this tag. Try {% img path/to/img.jpg [coma, separated, tags] %}."
end
end
def render(context)
storeImgTags(context) if defined?(@tags) # store datas if we have tags
site = context.registers[:site]
imgTag = "<a href='#{ site.baseurl }/assets/#{@url}'><img src='#{ site.baseurl }/assets/#{@url}' /></a>"
end
def storeImgTags(context)
# store tagged images datas in site config under the key site.config['images-tags']
imagesTags = context.registers[:site].config['images-tags'] || {}
@tags.each{|tag|
slug = Utils.slugify(tag) # My tag -> my-tag
# create a tag.slug entry if it doesn't exist
imagesTags[slug] = imagesTags[slug] || {'name' => tag, 'images' => [] }
# add image url in the tag.images array if the url doesn't already exist
# this avoid duplicates
imagesTags[slug]['images'] |= [@url.to_s]
}
context.registers[:site].config['images-tags'] = imagesTags
end
end
end
Liquid::Template.register_tag('img', Jekyll::ImgWithTags)
此时:所有标记图像 link 均已呈现,所有标记->图像关联已存储。
_plugins/hook-site-post-render-imagesTagsPagesGenerator.rb
Jekyll::Hooks.register :site, :post_render do |site, payload|
puts "++++++ site post_render hook : generating Images Tags pages"
imagesTags = site.config['images-tags'] # datas stored by img tag
linksDatas = site.data['imagesTagsLinks'] # tags pages link in data file
pagesFolder = 'tag'
imagesTags.each do |slug, datas|
tagName = datas['name']
tagImages = datas['images']
pageDir = File.join(pagesFolder, slug)
tagPage = Jekyll::ImageTagPage.new(site, site.source, pageDir, tagName, tagImages)
# as page rendering has already fired we do it again for our new pages
tagPage.output = Jekyll::Renderer.new(site, tagPage, payload).run
tagPage.trigger_hooks(:post_render)
site.pages << tagPage
# verbose check to see if we reference every tag url in out data file
if !linksDatas.key?(tagName) # check if tag is in imagesTagsLinks data file
puts "Warning ---------> #{tagName} not in data file"
puts "Add : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
else
if tagPage.url != linksDatas[tagName] then # check if url is correct in imagesTagsLinks data file
puts "Warning ---------> incorrect url for '#{tagName}'"
puts "Replace : #{tagName}: #{linksDatas[tagName]}"
puts "by : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
end
end
end
puts "++++++ END site post_render hook"
end
module Jekyll
class ImageTagPage < Page
def initialize(site, base, dir, tag, images)
@site = site
@base = base
@dir = dir
@name = 'index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'tag_index.html')
self.data['tag'] = tag
self.data['images'] = images
self.data['title'] = "Images for tag : #{tag}"
end
end
end
以及标签布局页面
_layouts/tag_index.html
---
layout: default
---
<h2>{{ page.title }}</h2>
{% for i in page.images %}
<img src="{{ site.baseurl }}/assets/{{ i }}" alt="Image tagged {{ page.tag }}">
{% endfor %}
至此,生成标签页面的一切就绪。
我们现在可以执行 jekyll build
并查看详细输出,告诉我们要在 _data/imagesTagsLinks.yml
_数据/imagesTagsLinks.yml
tag1: /tag/tag1/
tag2: /tag/tag2/
...
我们现在可以 link 从任何地方通过一个简单的
到我们的标签页{% for t in site.data.imagesTagsLinks %}
<li><a href="{{ site.baseurl }}{{ t[1] }}">{{ t[0] }}</a></li>
{% endfor %}
我告诉过你:这很棘手。但它完成了工作。
注意:img
标签可以改进,为什么 figure
标签不行?