忍者ブログ
Admin / Write / Res
ちゃんとカテゴリ分けされておりませんので、 記事をお探しならブログ内検索が便利です。 ご活用くださいませー+.(≧∀≦)゚+.゚
ブログ内検索
カレンダー
10 2024/11 12
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
カウンター
アクセスカウンター
最新コメント
[11/22 รูปพวงหรีดแสดงความเสียใจ]
[11/22 ดอกไม้ งานศพ]
[11/22 ช่อดอกไม้ตามสั่ง]
[11/22 ร้านดอกไม้บรรยากาศอบอุ่น]
[11/21 Robertret]
最新トラックバック
プロフィール
+ハンドル+
y_ayamori(purple)
+職業+
IT系エンジニア
+すまい+
さいたま
バーコード
[1]  [2]  [3]  [4]  [5]  [6
クロールはあまり大きな声で言えませんが私生活上身近な存在です。
そしてクロールをするうえで非常に重要になるのが、いかにコンテンツを取得するかとなります。

それはWEBサイト運営者の身になって考えるとわかるのですが、コンテンツ提供者にとってbotのアクセスは望まざる来訪者です。
時に負荷をかけるだけで一文の得にもならないどころかコンテンツを流用されて被害すら出ます。
そのためクロールという行為そのものが受け入れる側としては好ましくありません。
時にはアクセスを遮断される事態に陥ります。

アクセスブロックという事象です。
単純なアクセスブロックは接続元のIPアドレスを元に遮断を行います。
つまりアクセス元が複数(のIP)あればかいくぐることができる(可能性が高まる)ということです。

そのために世の中のボットはサーバを仲介してアクセス元を偽装しコンテンツの取得を試みます。
通称プロキシというものです。
アクセス元をごまかせれば何でもいいので要はIPなのですが、個人(法人であっても)IPを手に入れるのは割と困難で費用も掛かります。
そこで安いVPSなどをレンタルして仲介することでアクセス元をごまかします。

しかしこんなことをする方であればご存知だと思いますがアクセス元のIPアドレスはまだまだIPv4が主流です。
そしてIPv4は既に割り当てが完了しています(枯渇状態)。
そうなってくるとこのIPの所有者はだれであるかは容易な話になってきます。
使用者は難しいですが、所有者は割と簡単です。

となるとアクセスされる側としては大事なのはどこから来たのか、となりますので、サーバから来た≒踏み台を使用して偽装アクセスしているの方程式が成り立ちますので、アクセスブロックを施策するわけです。
こうしてアクセスされる側は大量のアクセスをブロック、踏み台をブロックという2段構えでコンテンツを守るわけです。

もしここまで施策しているサイトからコンテンツを取得したいとなると容易ではありません。
しかしブロックの仕組みがIPアドレスのみで判断している場合はかいくぐれる可能性が高い方法があります。

それが tor です。

前置きが長くなりましたが、torの構築メモとなります。
こういうニッチでグレーな環境を構築するにはUbuntuOSが手っ取り早いでしょう。

# tor のインストール
sudo apt install tor

# tor サービスの起動
sudo systemctl start tor

# IPをすぐに変える場合はサービスの再起動が手っ取り早い
sudo systemctl restart tor

# クロールテスト(自分の生IP)
curl -s http://taruo.net/ip/ | egrep '[0-9.]{8,16}'
# クロールテスト(torのIP)
curl -s -x socks5h://127.0.0.1:9050 http://taruo.net/ip/ | egrep '[0-9.]{8,16}'

どうでしょうか。生IPから変ってIPを偽装されているのがわかると思います。
しかし tor ではデフォルトで localhost を Listen します。
クロールサーバと tor サーバが抱き合わせならこれでもいいですが、別にする場合はサーバIPのほうが良いです。
設定でループバックアドレスからローカルIPに変更することはできると思いますが、ここでは手っ取り早くポートフォワーディングで乗り切ってみようと思います。

# ポートフォワーディング専用コマンドのインストール
sudo apt install redir

# ポートフォワーディングの設定(8080->127.0.0.1:9050)
redir --lport=8080 --cport=9050 --caddr=127.0.0.1

#tor
#クロール
#プロキシ
#UbuntuServer24.04


拍手

PR
djangoのPermissionはわかりにくいですよね。
恐らくやり方だけが出回っているため、その全体像がイメージしにくいために把握に時間が掛かってしまうのだと思います。

私もかなり調べました。
djangoのPermissionの考え方はシンプルでCRUDに基づき、追加・削除・更新・閲覧がデフォルトで用意されています。
そしてその権限はアプリとモデルに紐づくということです。

アプリに紐づくというのはイメージしやすいのですがモデルに紐づくというのがちょっと混乱を招いている気がします。
というのも権限の範囲がアプリというスコープなのはイメージしやすいですが1アプリの中でモデルは複数存在するものではないかと思います。
にもかかわらず権限はモデルに紐づくため、モデルと言ってもどのモデルを使えば…?
という疑問から始まってしまいます。

しかもモデルに紐づけている割にはその仕組みをコンテントタイプ(ContentType)というここにきて新しい概念で括ってきます。
これらの立て付けをちゃんと説明しているサイトが少なく、権限付与のやり方という結論しかないため難しくしているのではないでしょうか。
ちなみにContentTypeはざっくりアプリ名とモデル名を紐づけたものです。

さらにContentTypeはdjangoアプリに。
permission自体はauthアプリに紐づくのもわかりにくい。
ここはもはや標準機能内のおはなしなのでそういうもの、で終わらせておきましょう。

これらから私はdjangoのPermissionsは以下のように立て付けることとしました。
アプリまたは業務スコープ内でPersmissionsテーブルを作ってしまう。
よくあるブログと投票の例でいうと

class BlogPost(models.Model):
    # ...


class Vote(models.Model):
    # ...
こんな感じがあったとしてブログを管理できる権限と管理ができる権限を分ける場合、こんな感じのモデルを作っちゃいます。
class BlogPermission(models.Model):
    class Meta:
        managed = False


class VotePermission(models.Model):
    class Meta:
        managed = False
Permissionはモデル(テーブル)に自動的に自動的に紐づくので、中身や管理も不要です。
managed=Falseでもパーミッションは作成されてしまうようなので、modelsに記載されているかどうかが重要のようです。
またモデルを消してもPermissionは残るので、もしかしたらカスタムPermissionのほうが良いかもしれません…
とはいえ権限の設定があることがmodelsに記載すること明白になるので、まったくメリットがないというわけじゃないと思っています。
なのでここまでできてしまえば、後は簡単。
# 必要なモデル群をimport
from django.contrib.auth.models import User, ContentType, Permission
from sample.models import BlogPermission

# ContentTypeを引き出して、該当の権限を引っ張る
content_type = ContentType.objects.get_for_model(BlogPermission)
permissions = Permission.objects.filter(content_type=content_type)

# それをユーザに紐づけるだけ
user.user_permissions.set(permissions)
if user.has_perm("sample.add_blogpermission"):
    print('権限あります')

# 上記はCRUD全てですが、特定の権限に絞る場合はこんな感じ
permissions = Permission.objects.filter(content_type=content_type, codename__startswith='delete')

次にグループです。
グループの概念がある割にグループに関する操作マニュアルが希薄でこれまたわからない…
どこにグループの作り方の記載あるのでしょうか…
テーブル見る限り、単純にINSERTで対応してしまえばよいみたいです…
ここもキャメルケースにすべきかどうかも不明ですね…
# グループを作成
group = Group(name='BlogAdmin')
group.save()

# グループが持つ権限をセット
permissions = Permission.objects.filter(content_type=content_type)
group.permissions.set(permissions)
group.save()

# ユーザにグループ権限を付与
user.groups.set([group])
慣れればこれだけ。
ただグループとユーザが同列のため、その権限はユーザPermissionなのかグループPermissionなのかはしっかり設計が必要です。

私は権限のスコープはモデルで、権限の塊はグループで分けることにしました。
# 閲覧のみ
group = Group(name='BlogViewer')
group.save()
permissions = Permission.objects.filter(content_type=content_type, codename__startswith='view')
group.permissions.set(permissions)
group.save()

# 編集者
group = Group(name='BlogEditor')
group.save()
group.permissions.set([Permission.objects.get(content_type=content_type, codename__startswith='view'),
                      Permission.objects.get(content_type=content_type, codename__startswith='add'),
                      Permission.objects.get(content_type=content_type, codename__startswith='change'),])
group.save()

少しでも参考になれば幸いです。

拍手

ガチdeメモ
sudo dnf install curl gcc openssl-devel bzip2-devel libffi-devel zlib-devel wget make -y
export CFLAGS="-fPIC"
./configure --enable-optimizations --prefix=${HOME}
make clean
make -j $(nproc)
make install

拍手

aaSで悩ましいのはコスト計算。
運用したら移行コストも含めてペイできないもよく聞きます。
最近では脱クラウド、オンプレ回帰という言葉もよく見ます。

しかしながらクラウドが便利であることには変わり有りません。
特にデータ周りはバックアップや耐障害性も踏まえるとaaSはとても優位です。

そんな中で新鋭とも呼べるaaSがTiDB。
MySQLベースのRDBMSのサービスでDaaSに分類されます。

そんなTiDBはDisk容量とRU、リクエストユニットというこれまたわからない使用量の単位で課金をしてきます。
Diskもシンプルかと思いきや、行ストレージと列ストレージがあります。
いったん行だけ考えます。
無料枠は5GiB、5000万RUまで。
単位を聞くとそこそこ使えそうです。

実際は、というと77MBのデータを保存して85MiB。
RUは66万です。
小さいアプリケーションならそこそこ使えそう。
ということでざっくり、1MB書き込み処理を行うのに10,000RU、1MB読み込み処理を行うのに100RUくらいという試算がでました。

ビッグデータをゴリゴリ解析するのでないなら5GiBはかなりの容量です。
5000万RUまで無料を考えるとRUも思ったより消費しませんね。

どこかで一度本運用してみたいと思います。

拍手

バージョンを落として解決!
とか何の解決にもなっていない記事が散見されるので備忘録。

必要なライブラリがないからpipで失敗するのでパッケージ管理コマンドで事前にインストールしておくだけです。
# Redhat系
sudo dnf install mariadb-connector-c-devel

# Debian系
sudo apt install libmysqlclient-dev

Refs: How to install libmysqlclient-dev at AlmaLinux 9.2
#Python3 #pip #mysql

拍手

画像をベースライン形式からプログレッシブ形式に変換する要件が出てきたので、楽な方法は無いかと検索したところ jpegtran コマンドがよさそうってなりました。
しかし dnf などで入らないようなのでコンパイルが必要です。
備忘録的にシェルスクリプトを作成しました。

# シンプルにインストール
curl http://notebook.mor-maid.info/scripts/jpegtran_install.sh | bash -
# インストール先などを変える場合はいったん保存が必要
# working_path はソースのダウンロードやコンパイルを行うディレクトリです
curl http://notebook.mor-maid.info/scripts/jpegtran_install.sh > jpegtran_install.sh
chmod +x jpegtran_install.sh
./jpegtran_install.sh -i path_to_install -w working_path
# インストールに必要な dnf などで入るパッケージも含めてインストールする場合は -d でやってくれます
# その場合は要rootユーザです
curl http://notebook.mor-maid.info/scripts/jpegtran_install.sh > jpegtran_install.sh
chmod +x jpegtran_install.sh
./jpegtran_install.sh -i /user/local/ -w working_path -d

refs: jpegtranのインストール方法と使い方【JPG画像最適化】
要望不具合はXにて賜ります

拍手

まぁ、ググれば出てくるんですが、まだググり方にコツがいるので、備忘録的に…
WEBサイトのテストや邪道な使い方としてクローラを作成するときにseleniumはよく使う手段です。
が、geckodriverはともかくchromedriverは毎回chromeのバージョンに合わせたchromedriverを使わなければなりません。
そのため、毎回chromedriverを起動するchromeに合わせて落としてくる必要があるのですが…
pipにて自動インストールするモジュールがありましたので、こちらを使うと便利ですよ、というお話しです。

またfind_element_by_xpathもなくなったようなので、合わせて代替方法も記載します。


事前作業
pip install selenium
pip install webdriver_manager

簡易的に確認
2023.08.21 更新
# 4.3.0 以降は呼び出し方が変わったみたいです

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager


service = Service(executable_path=ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
driver.get('https://yahoo.co.jp/')
driver.find_elements(By.XPATH, '//a')

# 4.3.0 以前のやりかた

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://yahoo.co.jp/')
driver.find_elements_by_xpath('//a')

検索タグ
#python #python3 #クローラ #chrome #chromedriver #selenium

拍手

バージョン管理は主に案件、システム単位で行うことは多いと思いますがそうなるとその単位でリポジトリを切ることになります。
ローカル、または共有サーバ上でディレクトリを作成してそれぞれにリポジトリを作ることはリポジトリの管理の面でとても楽ちんです。

一方でローカル、またはイントラにあるネットワークからはデプロイが困難という側面もあります。
高度なインテグレーション体制(CIツールの利用)があれば、解決可能でしょうが、そこに至らない小規模開発ベンチャーにはハードルが上がります。<br />
<br />
またアクセス権という意味ではしっかりしておかないと、リポジトリにアクセスできる人はどのリポジトリにもアクセス可能になってしまいます。<br />
githubなどはそれらをうまく回避可能なのでしょうが、Mercurialではどうでしょうか、ということで前置き長くなりましたが、hgwebの導入について、です。<br />
<br />
hgwebの特徴<br />
・WEB経由で行える<br />
・リバプロで対応することでインターネットはSSL通信を容易に実現可能
・BASIC認証などを組み合わせればアクセス制限を簡易的に実現できる


ほぼ以下を丸パクリ<br />
https://github.com/benoitc/gunicorn-recipes/issues/1
 
でもいくつか思い通りにならないので後ほど修正します。
<br />
事前準備
<pre>
# 必要なモジュールを pip で入れていく
# 必要に応じてvenvは事前にして置くこと
pip install mercurial
 
# リポジトリ群を格納するディレクトリを作成(場所は任意)
mkdir -p /var/vcs/mercurial/repos
# hgwebの設定を諸々記載するディレクトリを作成(場所は任意)
mkdir -p /var/vcs/mercurial/hgweb
 
# hgweb.py を作っていく
vim /var/vcs/mercurial/hgweb/hgweb.py
----

from mercurial.hgweb import hgweb

# bytes にするところがミソ
CONFIG = b'./hgweb.config'
app = hgweb(CONFIG)
 
----
 
# hgweb config を作っていく
vim /var/vcs/mercurial/hgweb/hgweb.config
----
 
[ui]
editor = vim
 
[web]
# 今回は /hgweb/ からリバプロからのリクエスト想定なのでこのようにする
baseurl = hgweb/
# 今回は paths でワイルドカードを指定し、動的(再帰的)にリポジトリを検索する
descend = True
# SSLはApacheで、リバプロと hgweb はイントラ内なのでSSLは無効にする
push_ssl = false
# pushを許可する
allow_push = *
 
[paths]
/ = /var/vcs/mercurial/repos/*
 
----
 
# gunicorn の設定
vim /var/vcs/mercurial/hgweb/gunicorn.conf.py
----
import pathlib
base_dir = pathlib.Path(__file__).parent
 
wsgi_app = 'hgweb:app'
 
host = "127.0.0.1"
port = "9000"
bind = f"{host}:{port}"
 
daemon = True
reload = True
----
 
# httpd.conf この辺は諸々省略します
----
cat << EOS > /etc/httpd/conf.d/hgweb.conf
ProxyPass /hgweb/ http://127.0.0.1:9000/
ProxyPassReverse /hgweb/ http://127.0.0.1:9000/
EOS
----
 
# リポジトリ作成
cd /var/vcs/mercurial/
hg init repos/test_repo && touch hgweb/gunicorn.conf.py
 
# リポジトリが見えることを確認する
https://hgweb.host/hgweb/
 
</pre>

拍手

すぐ忘れてしまうのでメモします。
Sc config wsearch start=disabled
Net stop wsearch

EsentUtl.exe /d C:\ProgramData\Microsoft\Search\Data\Applications\Windows\Windows.edb

Sc config wsearch start=delayed-auto

Net start wsearch

拍手

Redmineでプロジェクト管理しているところは多いのではないでしょうか。
最近はバッグログやJIRAなどが台頭し、インターフェースもお堅めなRedmineは時代遅れなイメージがあります。
比較的中規模以上の案件で真価を発揮するタイプだと思うので、
・まずは使ってみる。
・少人数の情シスが使う。
・個人のタスク管理に使う。
には向かないと思います。

しかしながら企業で採用されていたり顧客先で導入されているとあらば、利用せざるを得ません。
どんな感じでつかえるのかなー、と思っても気軽に構築するのも割と手間だったりします。

sqlite3でそこでとりあえずサクッと、動かしたい。
あの機能はどの権限で使えるんだっけ?
この権限付与するとどうなるの?
このボタン押すと取り消しつかない??
そんな悩みはエンジニアならまず使ってみよう精神で突破したい。
少なくともあたしはそうなのよね。

なので、インストーラ作ってみました。
# Ubuntsu Server 20.04LTS
wget 'http://notebook.mor-maid.info/scripts/redmine.sh'
sudo sh redmine.sh

本当にまっさらなOSに一からインストールし、自由に操作可能な場合のみです。
DBやMailなど設定しませんので決してプロダクション環境で使用しないように!
refs: https://kojion.com/posts/894

拍手

Copyright ©  アナログを愛するデジタル生活館 All Rights Reserved.
* material by Pearl Box   * Template by tsukika

忍者ブログ [PR]