そのため、数分ごとに広告をチェックするサービスを探すのではなく、何か面白いものが表示された場合に通知されますか? 同時に、SMSで通知するのが最善です。そうしないと、メールをすぐに確認できないことがあります。
Googleは、SMSごとに3ルーブルから、または1日あたり4ルーブルから「のみ」、そのようなサービスをいくつか発行しています。
最終的に、私はそのようなサービスを自分で書くことにしましたが、それについては後で詳しく説明します...
楽しみのために、サービスの1つにサインアップしました。 昨日、彼は15分ごとにリンクをチェックし、何か変更があった場合はメールに通知を送信しました。 彼らのウェブサイトのSMSについては、mail.ruメールがSMSを送信できるとさりげなく言及されました。 実際、mail.ruはメガホンでしか送信できないことが判明しましたが、私にはありません...そして、Beeline-MTSが必要な場合は、サービスが有料で喜んでお手伝いします。
また、私は長い間非常に便利で無料のサービスのユーザーであり、特定の件名のメールを特定のメールボックスに送信できるようにしました。これにより、メールの内容がSMSの形で私に届きます。 サービスレターにmy_yaschik@sms.ruを指定したかったのですが、SMSを受信しないと、レターの件名を変更する方法がわかりませんでした。
さらに、今日グリスのデモ期間は終了し、検証頻度は720分になりました。
一般的に、このレベルの「サービス」は
このスクリプトにはVPSホスティングを使用しました。 WEBホスティングも適切です。ただし、その上に真珠、「外部」アクセス、およびスケジューラーがある場合に限ります。 極端な場合、インターネットに含まれるコンピューターが適しています。 多くの人が似たようなものを持っていると思います。
スクリプトは何に書かれていますか
私は真珠の上にそれを書くことにしました、そして、私は真珠をかなり平凡に知っていますが、それはこの種のスクリプトに最も適しています。 真珠を扱うのが面倒だったところで、私は本当に緊張しませんでした、私はシステムを通してシェルコマンドを呼び出しました。 それにもかかわらず、私の意見では、それはかなりうまくいき、私の創造物を一般に公開することをnotしませんでした。
仕事の論理、簡単に
-xxx分ごとにスクリプトを実行します。
-wgetを使用してページをダウンロードします。
-前回ダウンロードしたページを保存し、新しくダウンロードしたページと比較します。アナウンスメントが変更されたり、新しいアナウンスが表示された場合は、これについてSMSを送信します。
広告から引き出されるINFAは次のとおりです。
1.広告URL(広告の一意の識別子として使用します);
2.名前;
3.価格。
同時に提供されるのは、ページのダウンロードの1つが突然クラッシュした場合、古いリストが残り、次回ページがダウンロードされるだけで、変更が発生した場合にSMSが変更を通知することです。
より詳細
使用する前に、メーラーとwgetのパスと名前を確認し、それらが存在することを確認して作業してください。 特に、私のcentosメーラーはmutt、mailまたはsendmailと呼ばれ、同じ構文がより一般的です。 たぶん、wgetを/ usr / local / bin / wgetなどに置き換える必要があるかもしれません。
また、通知を受信するメールボックスと電話を設定する必要があります。
コマンド./avito.pl url_pages_with_advertsを使用してスクリプトを実行します。
ページのURLは「写真付きリスト」の形式にする必要があります。 つまり、URLに&view = listまたは&view = galleryを含めないでください。
URLの例: www.avito.ru/moskva?q=%D1%80%D0%B5%D0%B7%D0%B8%D0%BD%D0%BE%D0%B2%D1%8B%D0%B9+% D1%81%D0%BB%D0%BE%D0%BD
このページは、urlから取得した名前のファイルにダウンロードされ、左のすべての文字が次のようにアンダースコアに置き換えられます。
https ___ www.avito.ru_moskva_q__D1_80_D0_B5_D0_B7_D0_B8_D0_BD_D0_BE_D0_B2_D1_8B_D0_B9__D1_81_D0_BB_D0_BE_D0_BD
一意であり、LinuxとWindowsの両方でサポートされていると同時に、十分に読み取り可能である必要があります。
そのようなファイルが既に存在する場合、スクリプトはそのファイルから広告をプルしようとします。 ファイル内に広告が見つからない場合、スクリプトはファイルを上書きしながらwgetを呼び出します。 広告が見つかった場合、ファイルはサフィックス-1で保存されます。
https ___ www.avito.ru_moskva_q__D1_80_D0_B5_D0_B7_D0_B8_D0_BD_D0_BE_D0_B2_D1_8B_D0_B9__D1_81_D0_BB_D0_BE_D0_BD-1
次に、ページが再度ダウンロードされ、次の状況がチェックされます。
1.新しいダウンロードページに広告が見つからない場合、スクリプトは単に終了します。古いページはサフィックス-1のままです。 これは、ネットワークが突然消失またはハングした場合に発生します。過去の広告リストは失われません。
2.スクリプトを初めて実行する場合(以前にダウンロードしたページが見つからなかった場合)、INFAは使用可能な広告の数について単純に通知します。
25のアイテムが見つかりました、ページwww.avito.ru/moskva?q=%D1%80%D0%B5%D0%B7%D0%B8%D0%BD%D0%BE%D0%B2%D1%8B%D0% B9 +%D1%81%D0%BB%D0%BE%D0%BDモニタリング開始
このメッセージが表示された場合、システムが起動しました。これは主にすべてが機能していることの確認です。
SMSは短いほうが良いため、すべてのメッセージは非常に簡潔です。
3.新しいアナウンスが表示された場合、これに関する情報が将来のSMSのテキストに追加されます。 その後、すべての広告について、INFAは1つのSMSの形式で提供されます。
4.製品の価格または名前が変更された場合、INFAは次の形式で表示されます:old_price-> new_price name link。 または、new_nameリンク。
名前を変更できるかどうかはわかりませんが、余分なチェックを行うのは残念ではありませんでした。
5.見つかったもののリストがコンソールに別のテキストで表示されます。 今日はパーサーが動作しているため、これはデバッグのためにより多く行われ、明日、マークアップを変更すると停止します。 解析を変更する必要があります。
解析とニュアンスについて
実際、すべての解析は次の行にあります。
while($text=~/<div class=\"description\"> <h3 class=\"title\"> <a href=\"(.*?)\".*?>\n(.*?)\n.*?<div class=\"about\">\n\s*(\S*)/gs)
ただし、価格にはnbspの形式のスペースも含まれています。
$price=~s/ //g
正式に言えば、構文解析はまだ1行ではなく、2行で行われます。
g-グローバル検索修飾子。これにより、while条件内に検索を配置し、毎回次の宣言を行うことができます。
s-1つの正規表現内で複数の行を検索できます(Avito URLでは、名前と価格は4行ですが、現在はレイアウトが変更されるまで)。
また、スクリプトの先頭でファイルの複数行の読み取りが割り当てられていることに注意してください。
undef $/;
これは私の$ text =; ファイル全体を読み取ります。
別のニュアンス:クリック可能なURLをすべてのSMSに挿入します。 私は通常のスマートフォンを持っているので、SMS内でURLを確認して、目的のページにアクセスすることができます。 そのため、何らかの理由でsms.ruはアンダースコアのような無邪気な性格を台無しにします。 それを%C2%A7に置き換えます。 影響を与えることはできませんが、アンダースコアコードに置き換えることができます。アンダースコアコードは通常表示されますが、sms.ruのURLはクリック可能になり、通常のメールの場合は同じままです。
スケジューラーにタスクを追加します
#crontab -e */20 * * * * cd /scripts/avito && ./avito.pl 'https://www.avito.ru/moskva?q=%D1%80%D0%B5%D0%B7%D0%B8%D0%BD%D0%BE%D0%B2%D1%8B%D0%B9+%D1%81%D0%BB%D0%BE%D0%BD'
20分ごとに、スクリプトを呼び出してページを確認します。 一重引用符でURLをエスケープすることを忘れないでください。
このようなタスクは必要に応じていくつでも依頼でき、それらはすべて互いに独立して動作します。
産業用オプションのために私がやっていなかったことと、完了しやすいこと
1.ユーザーとタスクを追加/削除するためのWebフェイス。 mysqlデータベース内のsms.ruのストレージURL、頻度、メールボックス、電話ユーザー。 スクリプトは毎分呼び出され、実行するURLを確認し、ハードコードされた番号ではなく、ユーザーが設定した番号にSMSを送信します。
そうすれば、1日8ルーブル程度でユーザーをはぎ取ることができます。 たぶんそれをする? そのようなことに対して支払いたい人はいますか?
2.価格フィルター。 設定価格より上または下の価格を無視します。
if: next if($page_new{"price"}{$uri}>$max_price or $page_new{"price"}{$uri}<$min_price)
、別の要素によって要素的に行われ
if: next if($page_new{"price"}{$uri}>$max_price or $page_new{"price"}{$uri}<$min_price)
。 ただする必要はありませんでした。
3. Avitoとの類推により、auto.ru、irrなどを追加します。 サイト。
また、
while(...){...}
だけ
while(...){...}
追加して、各サイトに1つずつ追加します。 主なことは、
$page{"name"}{$uri} $page{"price"}{$uri}
がそれらの中に埋められていることです。
各サイトは
while
をトリガーし、残りは単に空の結果を返します。
さて、実際にはスクリプトコード
#!/usr/bin/perl use strict; undef $/; my $url=$ARGV[0]; my $mailer="mutt"; my $wget="wget"; if($url eq ""){ print "Usage: avito.pl <https://www.avito.ru/...url>"; exit; } my $filename=$url; $filename=~s#[^A-Za-z0-9\.]#_#g; $url=~m#(^.*?://.*?)/#; my $site=$1; print "site:".$site."\n"; sub sendsms { my $text=shift; $text=~s/_/%5F/g; $text=~s/&/%26/g; system("echo '$text' | $mailer -s 79xxxxxxxxx xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\@sms.ru"); } sub parse_page { open(MYFILE,"<".shift); my $text=<MYFILE>; close(MYFILE); my %page; while($text=~/<div class=\"description\"> <h3 class=\"title\"> <a href=\"(.*?)\".*?>\n(.*?)\n.*?<div class=\"about\">\n\s*(\S*)/gs) { my $uri=$1; my $name=$2; my $price=$3; $uri=~s/^\s+|\s+$//g; $name=~s/^\s+|\s+$//g; $price=~s/^\s+|\s+$//g; $price=~s/ //g; $page{"name"}{$uri}=$name; $page{"price"}{$uri}=$price; } return %page; } my %page_old=parse_page($filename); if(scalar keys %{$page_old{"name"}}>0){ system("cp $filename ${filename}-1"); } else{ %page_old=parse_page("${filename}-1"); } system("$wget '$url' -O $filename"); my %page_new=parse_page($filename); if(scalar keys %{$page_old{"name"}}>0){ # already have previous successful search if(scalar keys %{$page_new{"name"}}>0){ # both searches have been successful my $smstext=""; foreach my $uri(keys %{$page_new{"name"}}) { if(!defined($page_old{"price"}{$uri})){ $smstext.="New: ".$page_new{"price"}{$uri}." ".$page_new{"name"}{$uri}." $site$uri\n "; } elsif($page_new{"price"}{$uri} ne $page_old{"price"}{$uri}){ $smstext.="Price ".$page_old{"price"}{$uri}." -> ".$page_new{"price"}{$uri}." ".$page_new{"name"}{$uri}." $site$uri\n"; } if(!defined($page_old{"name"}{$uri})){ # already done for price } elsif($page_new{"name"}{$uri} ne $page_old{"name"}{$uri}){ $smstext.="Name changed from ".$page_old{"name"}{$uri}." to ".$page_new{"name"}{$uri}." for $site$uri\n"; } } if($smstext ne ""){ sendsms($smstext); } } else{ # previous search is successful, but current one is failed # do nothing, probably a temporary problem } } else{ # is new search if(scalar keys %{$page_new{"name"}}<=0){ # both this and previous have been failed sendsms("Error, nothing found for page '$url'"); } else{ # successful search and items found sendsms("Found ".(scalar keys %{$page_new{"name"}})." items, page '$url' monitoring started"); } } foreach my $uri(keys %{$page_new{"name"}}) { print "uri: $uri, name: ".$page_new{"name"}{$uri}.", price: ".$page_new{"price"}{$uri}."\n"; if($page_new{"price"}{$uri} eq $page_old{"price"}{$uri}){print "old price the same\n";} else{print "old price = ".$page_old{"price"}{$uri}."\n";} if($page_new{"name"}{$uri} eq $page_old{"name"}{$uri}){print "old name the same\n";} else{print "old name = ".$page_old{"name"}{$uri}."\n";} }