読者です 読者をやめる 読者になる 読者になる

h365info's blog

http://h365.info というアダルトサイトの管理人のブログ

自動相互リンクチェック機能の実装方法

今日は自動相互リンクチェック機能の実装の説明をしたいと思います。

相互リンクとはご存知のとおり、AというサイトとBというサイトがお互いにリンクを張り合うというものです。検索エンジンSEO として有名なやつです。

相互リンクは一昔前はメールで連絡をとりあってお互いにリンクを張り合うという作業が多かったと思いますが、最近では自動で相手のサイトに自分のURLが登録されているかを確認して、自分のサイトのURLがあればこちらもリンクを登録するという形式が増えています。

その機能を Rails で実装してみます。

実装の参考は h365.info を御覧ください。アダルトサイトなので見るときは気をつけてください。

相互リンクと新規登録 - [H365]エッチなエロ動画を365日厳選配信(スマートフォン対応)

Link モデルを作成する

bundle exec rails g model Link

db/migrate/20140201150636_create_links.rb

class CreateLinks < ActiveRecord::Migration
  def change
    create_table :links do |t|
      t.string :title, null: false
      t.string :url, null: false
      t.string :comment
      t.string :validation_url
      t.boolean :invalid_url, default: false

      t.timestamps
    end

    add_index :links, :url, unique: true
  end
end

urlvalidation_url を分けているのは、リンク先として登録する URL (トップページがほとんどだと思います)とリンク集のページが違うことが多いからです。

models/link.rb

require 'open-uri'

class Link < ActiveRecord::Base
  before_validation :normalize
  validates :title, presence: true
  validates :url, presence: true, uniqueness: true
  validates :validation_url, presence: true
  validate :cross_linkable

  class << self
    def sweep_unlinked_site
      Link.find_each do |link|
        unless valid_site?(link.validation_url)
          link.invalid_url = true
          link.save(validate: false)
        end
      end
    end

    def valid_site?(url)
      uri = URI.parse(url)
      doc = Nokogiri::HTML(open(uri, 'Referer' => Settings.site.url))
      doc.xpath("//a[@href='#{Settings.site.url.chomp('/')}']", "//a[@href='#{Settings.site.url}']").present?
    rescue => e
      logger.warn "Link site validation exception: #{e.message}"
      false
    end
  end

  def cross_linkable
    if errors.empty?
        errors.add(:validaion_url, I18n.t('errors.invalid_validation_url')) unless Link.valid_site?(self.validation_url)
    end
  end

  private

  def normalize
    self.url.chomp!('/') if self.url && self.url.end_with?('/')
  end
end

open-urinokogiri を使ってリンク先のページを見に行き、URL が含まれているかを確認しています。

f:id:h365info:20140203123322p:plain