جادی تی وی ۰۱۰ – بررسی مشکلات اختراع دوباره چرخ با کمک پایتون و اسکرپینگ و ردیس

همراه اول یک سیستم فروشگاه درست کرده و کپچای بامزه ای هم براش گذاشته، اما مشکل اینجاست که دو چیز رو هیچ وقت نباید دوباره اختراع کرد: کپچا و رمزنگاری. در این شماره با اسکرپینگ، پایتون و کمی آمار از دیتا استور ردیس استفاده می کنیم تا ببینیم مشکل اختراع دوباره چرخ چیه!

لینک روی یوتیوب و هر کس هر جای دیگه آپلود کنه و لینک بده، باعث خوشحالی و دعای خیر پشت سانسوری‌هاست (:

آپدیت: انواع لینک دانلود در کامنت ها (:
آپدیت: دوستان در کامنت ها چندین بار گفتن که چرا توی بش چند صد بار برنامه رو اجرا کردیم. در واقع این ویدئوها آموزشی هستن و ایده شون این نیست که راحتترین روش انجام یک چیز رو نشون بدن. می خوایم حتما از ردیس استفاده کرده باشیم اینجا. نشون بدیم که چطوری می شه پیچیدگی برنامه نویسی رو با یک معماری خوب به حداقل رسوند. چطوری می شه یک سیستم رو قابل اجرا روی چندین کامپیوتر مختلف کرد و اصولا ردیس چیه (: معلومه که «ساده ترین» روش نوشتن این برنامه خاص این بود که توی پایتون یک لوپ و کمی آسینک قاطی کنیم و نتایج رو توی یک دیکشنری بشمریم. البته در عمل اون پیچیدگی هایی داشت تا به این سرعت برسه ولی خب برنامه نویسی سنتی تری بود. دقیقا ایده این ویدئو کست این بود که نشون بدیم چطوری باید اجزای شناخته شده و بسیار قوی رو ترکیب کرد تا به سادگی به یک سیستم با قابلیت بسیار بالا رسید.

شطرنج مخفی در مسنجر فیسبوک رو فعال کنید

chess

مسنجر فیسبوک چیز فوق العاده‌ای است. من هر وقت بحث تکنولوژی می شه مثالش می زنم و در موردش نظر می دم ولی خب متاسفانه تا حالا وقت نشده تو وبلاگ بهش بپردازیم. توی این مسنجر شما می تونین:

  • چت کنین
  • استیکر و عکس و … بفرستین
  • تماس تصویری بگیرین
  • پول جابجا کنین

و شطرنج بازی کنین. برای اینکار کافیه به سادگی پیامی با این بفرستین:

@fbchess play

کسی که بازی رو شروع کرده مهره‌های سفید رو داره و کافیه دستورات استاندارد شطرنجی بهش بگین. مثلا:

@fbchess b3 #پیاده ستون بی، به خونه سوم بره
@fbchess Nf3 #اسب به خونه اف سه
...
@fbchess help #راهنما لطفا

اوه.. این هم لازمه گفته بشه که شطرنج معمولا درست به ما معرفی نشده. ما فکر می کنیم شطرنج یک شکل فکر کردن پیچیده و تو در تو لازم داره در حالی که برای لذت بردن از شطرنج، باید اونو شبیه چیزی مثل لینوکس، نقاشی یا اسکیت دید. چیزی که شناختن و ور رفتن و فیلم دیدن و نگاه کردن و سخنرانی گوش کردن توش باعث می شه بازی ما خوب بشه. خیلی های ما شطرنج رو دوست نداریم چون توش می بازیم و حس می کنیم به اندازه کافی باهوش، دقیق، خفن نیستیم در حالی که ما می بازیم چون ازش لذت نمی بریم. درست مثل کسی که سعی کنه با فکر کردن استاد لینوکس بشه و بعد ناراحت بشه که چرا نتونست سوییچ ها رو به شکل صحیحی «حدس بزنه». در مقابل اگر مدتی لینوکس کار کنین، کنفرانس بیاین، فیلم ببینین، به راحتی می تونین شروع به «حدس زدن» سوییچ های هر دستور بکنین (:

چرا گنو/لینوکس رو دوست دارم:‌ فهرست کردن کل فایل‌های قابل دانلود یک سایت

یک دوستی پرسیده که چطوری می تونیم فهرست همه فایل‌های قابل دانلود در سروری مثل dl.folan.net رو داشته باشیم. این سرور اجازه می‌ده شما دایرکتوری‌هاش رو ببینین:

Screenshot from 2015-11-25 11-57-46

و مثلا توی دایرکتوری فیلم‌ها:

Screenshot from 2015-11-25 11-58-08

درست؟ دوست همیشگی ما در سری چرا گنو/لینوکس رو دوست دارم دستور جذاب wget است. پس شروع می کنیم!

$ wget --spider --force-html -r -l5 htp://dl.folan.net/Movie/

می تونه به شکل یک اسپایدر فایل‌های اچ تی ام ال رو می‌گیره و توشون رو نگاه می کنه و پاک می کنه و اینکار رو تا پنج شاخه داخل دایرکتوری‌ها هم پی‌ می‌گیره. البته اگر ارور بگیریم، دردسر درست می‌شه پس با اضافه کردن یک عبارت کوچیک، ارورها رو هم به خروجی اضافه می کنیم:

$ wget --spider --force-html -r -l5 htp://dl.folan.net/Movie/ 2>&1 

این دستور خروجی‌هایی شبیه به این تولید می کنه:

Spider mode enabled. Check if remote file exists.
--2015-11-25 12:02:51--  htp://dl.folan.net/Movie/5/American.History.X.1998.720p.folan.Net.mkv
Reusing existing connection to dl.folan.net:80.
htp request sent, awaiting response... 200 OK
Length: 785963069 (750M) [application/octet-stream]
Remote file exists but does not contain any link -- not retrieving.

Removing dl.folan.net/Movie/5/American.History.X.1998.720p.folan.Net.mkv.
unlink: No such file or directory

Spider mode enabled. Check if remote file exists.
--2015-11-25 12:02:51--  htp://dl.folan.net/Movie/5/American.Justice.2015.1080p.folan.Net.mkv
Reusing existing connection to dl.folan.net:80.

من خط‌هایی رو می‌خوام که اولشون — داره و پس می ریم سراغ grep که می‌تونه توی یک متن خط‌هایی رو جدا کنه که چیز خاصی توشون هست:

$ wget --spider --force-html -r -l5 htp://dl.folan.net/Movie/ 2>&1 | grep '^--'
--2015-11-25 12:04:57--  htp://dl.folan.net/Movie/4/A.Good.Day.to.Die.Hard.2013.720p.folan.Net.mkv
--2015-11-25 12:04:57--  htp://dl.folan.net/Movie/4/A.Good.Marriage.2014.BluRay.720p.folan.Net.Mkv
--2015-11-25 12:04:57--  htp://dl.folan.net/Movie/4/A.Hijacking.2012.720p.folan.Net.mkv

و خب حالا می تونیم فقط بخش یو آر ال رو جدا کنیم. با استفاده از awk:

$ wget --spider --force-html -r -l5 htp://dl.folan.net/Movie/ 2>&1 | grep '^--' | awk '{ print $3 }' 
htp://dl.folan.net/6piljd5xepub7trr13ke.gif
htp://dl.folan.net/85film3.gif
htp://dl.folan.net/Movie/1/Into.the.Woods.2014.720p.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/Iyobinte.Pusthakam.2014.720p.DVDrip.%5Bfolan.Net%5D.mp4
htp://dl.folan.net/Movie/1/Kick.2014.720p.BluRay.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/La.Grande.Illusion.1937.720p.Farsi.Dubbed.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/Late.Phases.2014.720p.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/Le-Week-End.720p.%5Bfolan.net%5D.mkv
htp://dl.folan.net/Movie/1/Legendary.2010.LIMITED.720p.%5Bfolan.Net%5D.mkv

و بعد فقط خط‌هایی رو نگه داریم که آخرشون چیزهایی مثل / یا css یا html و .. نداره:

$ wget --spider --force-html -r -l5 htp://dl.folan.net/Movie/ 2>&1 | grep '^--' | awk '{ print $3 }' | grep -v '\.\(css\|js\|png\|gif\|jpg\)$' | grep -v '\/$' 
htp://dl.folan.net/Movie/1/Into.the.Woods.2014.720p.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/Iyobinte.Pusthakam.2014.720p.DVDrip.%5Bfolan.Net%5D.mp4
htp://dl.folan.net/Movie/1/Kick.2014.720p.BluRay.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/La.Grande.Illusion.1937.720p.Farsi.Dubbed.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/Late.Phases.2014.720p.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/1/Le-Week-End.720p.%5Bfolan.net%5D.mkv
htp://dl.folan.net/Movie/1/Legendary.2010.LIMITED.720p.%5Bfolan.Net%5D.mkv

ایول. حالا کافیه همه چیز رو بریزیم توی یک فایل و خروی‌ها رو یک چکی بکنیم که درست باشه:

$ sort -R all.urls | head
htp://dl.folan.net/Movie/5/Modern.Times.1936.720p.Farsi.Dubbed.folan.Net.mkv
htp://dl.folan.net/Serial/The%20Killing/S01/The.Killing.S01E08.480p.folan.Net.mkv.folan.Net.mkv.mkv
htp://dl.folan.net/Serial/Breaking%20Bad/S05/BreakingBad.S05E06.folan.Net.mkv
htp://dl.folan.net/Movie/2/Priest.of.Evil.2010.720p.%5Bfolan.Net%5D.mkv
htp://dl.folan.net/Movie/5/A.Midsummer.Nights.Dream.1999.720p.WEB-DL.folan.Net.mkv
htp://dl.folan.net/Serial/Castle/S05/Castle.S05E22.480p.folan.Net.mkv
htp://dl.folan.net/Serial/Twin%20Peaks/S02/Twin.Peaks.S02E22.480p.folan.Net.mkv
htp://dl.folan.net/Serial/Supernatural/S04/SN-S04_E11.folan.Net.mkv
htp://dl.folan.net/Movie/Problem%20Child%201990/Bacheye.DardesarSaz.1990.720pWEB-DL.HQ_folan.info.mkv
htp://dl.folan.net/Serial/Archer/S01/Archer.S01E08.folan.Net.mkv

$ wc -l all.urls 
11284 all.urls

اینجوری فهرستی از ۱۱هزار فایل قابل دانلود اون سایتی که تصمیم گرفتم به خاطر حفظ بیزنسش، آدرسش رو ندم رو داشته باشیم (: هدف این پست دانلود نیست،‌ یاد گرفتن شیوه کار با لینوکسه و همچنین دقت کنین که http ها رو کردم htp که وبلاگ سعی نکنه به عنوان فیلم لودشون کنه از یو آر ال گفته شده (: خوش باشین و خندون و توانمند.

جلوی باگ شیما رو بگیرین! کسی دوست نداره بهش بگن «شیما عزیز خوش اومدی»

به جز عنوان واقعا چیز زیادی برای گفتن نیست. توی فارسی وقتی اسمی به الف یا و ختم بشه و ما بهش بگیم «$اسم عزیز خوش اومدی» یک باگ ریز پیش میاد. مثلا این برنامه رو نگاه کنین:

package main

import "fmt"

func main() {
  var name string = "کاربر"
  for name != "رفتم" {
      fmt.Print(name, " عزیز خوش اومدی.\n\n")
      fmt.Print("حالا اسم جدیدت رو بده: ")
      fmt.Scanln(&name)
  }
}

که نمونه اجراش می‌شه این:

$ go run 1.go 
کاربر عزیز خوش اومدی.

حالا اسم جدیدت رو بده: جادی
جادی عزیز خوش اومدی.

حالا اسم جدیدت رو بده: شیما
شیما عزیز خوش اومدی.

حالا اسم جدیدت رو بده: رفتم

و درست همینجا است که شیما به من ایمیل زده و گفته وقتی سایتی بهش می گه «شیما عزیز خوش اومدی» اصلا براش جذاب نیست. پس برنامه باید این شکلی باشه:

package main

import "fmt"

func main() {
  var name string = "کاربر"
  var greeter string
  for name != "رفتم" {
      if (name[len(name)-2:] == "ا") || (name[len(name)-2:] == "و") {
        greeter = name + "ی"
      } else {
        greeter = name
      }
      fmt.Print(greeter, " عزیز خوش اومدی.\n\n")
      fmt.Print("حالا اسم جدیدت رو بده: ")
      fmt.Scanln(&name)
  }
}

که خروجی شخصی‌ترین شبیه این بده:

$ go run 1.go 
کاربر عزیز خوش اومدی.

حالا اسم جدیدت رو بده: جادی
جادی عزیز خوش اومدی.

حالا اسم جدیدت رو بده: شیما
شیمای عزیز خوش اومدی.

حالا اسم جدیدت رو بده: شاهو
شاهوی عزیز خوش اومدی.

حالا اسم جدیدت رو بده: رفتم

خوبه؟ پس یک if جلوی باگ شیما رو بگیرین تا افرادی که اسمشون با الف یا و نموم می‌شه حس نکنن یک باگ در برنامه شما هستن.

کت کافی نیست، سیستم ادمین‌ها مواظب اسکریپت‌های بدجنس باشن

دوست خوب هکرم میلاد زنگنه نکته جالبی رو بهم یادآوری کرده:

امروز یه چیز جالب دیدم که نشون میده که برنامه هایی مثل cat و … خروجی کاملی از اون چیزی که واقعا درون فایل هست بهمون نشون نمیدن. برای مثال:

escape sequences

دلیل این اتفاق اینه که cat واقعا همه کاراکترها رو به همون شکلی که هستن توی خروجی استاندارد برامون چاپ نمیکنه و وقتی به \033[2A ( یا بطور کلی تر \033[XA )میرسه یکار خاص میکنه. این عبارت باعث میشه وقتی برنامه به این قسمت رسید به تعداد X خط (توی این مثال X دو هست) کرسر رو بالا ببره و باعث بشه X خط بالایی بازنویسی شه و در نتیجه باعث بشه ما گول بخوریم!
چنین چیزی ممکنه خیلی برای افراد عادی با اهمیت جلوه نکنه اما برای ادمین ها و لینوکسی ها که دائم با اسکرپت ها سرو کار دارن مهمه چون با همچین حقه ای ممکنه بدون اینکه بفهمن اسکریپت های مخربی رو اجرا کنن.

حرفش کاملا درسته و اکثرا هم می‌دونیم که Escape Characterها می‌تونن خروجی ترمینال رو تغییر بدن (مثلا رنگی کنن، پاک کنن، جابجا کنن، …) ولی اکثرا توجه نمی‌کنیم که یک اسکریپت در cat ممکنه چیز دیگه ای از اون چیزی که واقعا هست نشون داده بشه. در کل همیشه می‌گیم که بدون فهمیدن هیچ چیزی نباید روی کامپیوترتون اجراش کنین و الان ظاهرا باید بگیم که بعضی اسکریپت ها حتی ممکنه اون چیزی که در لحظات اول به نظر می‌رسن هم نباشن! یک مدیر سیستم مثل گرگ با چشم باز می‌خوابه!

پی.نوشت. ایریکس اشاره کرد که می‌شه از سوییچ A در دستور cat استفاده کرد تا همه کاراکترها اونطوری که واقعا هستن دیده بشن (زندگی از این سوییچ‌ها نداره؟ البته اگر داشت خیلی لوس می شد فضا)

روشی برای ارزیابی پیشنهادهای شغلی: در یکی از جلسات شرکت، شرکت کنید

scrum
(اسد صفری در حال آموزش اسکرام – عکس صد در صد باربطی نیست ولی عکس بهتری پیدا نکردم)

فرض کنین که پیشنهاد شغلی خوبی گرفتین ولی هنوز مطمئن نیستین که آیا می‌خواین به اون شرکت برین یا نه (خیلی لوکسه؟ نگران نباشین، خیلی زود براتون پیش می‌یاد). چه راه حلی دارین؟ صبر کردن؟ فکر کردن؟ مشورت کردن؟ کیمبرلی کسپر در یک مطلب جالب توی بی‌بی‌سی پیشنهاد جالبی داره:

حضور در یکی از جلسات کاری اون شرکت به شما در مورد تیمی که قراره توش باشین، شخصیت‌ آدم‌هاش و روشی که مدیر شما تیمش رو مدیریت می‌کنه، دید می‌ده. معلومه که چنین فرصتی نصیب هرکسی نمی‌شه اما درخواست کردنش ضرری نداره. حواستون باشه که این مساله رو بهتره با منابع انسانی مطرح نکنین چون پیام اشتباهی می‌فرسته. این درخواست رو از مدیر مستقیمتون بکنین و بخواین که توی یکی از جلسه‌های تیم آینده‌تون شرکت کنین.

منطقی نیست؟ من بعد از سال‌ها تجربه و عوض کردن چند شرکت به نظرم می‌یاد این یکی از بهترین توصیه‌های ممکن در وقتی است که آدم نمی‌دونه می‌خواد عضو تیمی باشه یا نه.

شیوه ساخت ویدئوهای آموزشی من که هم صفحه ضبط میشه، هم صدا هم تصویر وب‌کم

چند تا ایمیل داشتم که بگم چطوری ویدئوهای آموزشی ام رو می‌سازم که این شکلی می شن:

screencast

اما قبل از گفتن اسم برنامه‌هام لازمه بگم که در دنیای لینوکس انتخاب ها خیلی خیلی زیاد هستن و هیچ چیزی جواب نهایی نیست. من فقط کمی ور رفتم و به این ترکیب رسیدم و در نتیجه ازش استفاده می کنم. اولین کار نمایش تصویر وبکم در گوشه پایین است. برای اینکار از mplayer که یک «پخش کننده به مفهوم عام» خیلی قوی است استفاده می کنم:

mplayer -tv driver=v4l2:width=320:height=240: -vo xv -vf mirror tv://  -geometry "99%:99%" -noborder -ontop

کاملا مشخصه. وبکم رو می خونه و با ابعاد مشخص در مکان مشخص نشونش می ده بدون اینکه پنجره دورش بکشه و همیشه هم روی پنجره‌های دیگه نگهش می‌داره. در مرحله دوم کافیه صدا و تصویر جاری رو ضبط کنم. برنامه مرسوم recordmydesktop است ولی من با kazam راحتترم و خودش صدا رو هم ضبط می کنه. من همیشه قبل از ضبط یکبار آزمایشی ضبط می کنم که مطمئن بشم همه چیز درست کار می کنه و بعد از ضبط با استفاده از Audacity صدا رو به شکل مجزا ادیت می کنم که کیفیتش بهتر بشه کمی درباره اش اینجا نوشته ام و بعد با استفاده از kdenlive ویدئو رو ادیت می کنم و اکسپورت مورد نظرم رو می گیرم و می‌رسم به چیزهایی مثل جادی تی وی و آموزش لینوکس ال پی آی ۱۰۱ جادی.

ببینم شما چه می کنین (:‌ لینک ها رو بفرستین که تبلیغ کنیم.

چگونه یک گیک لینوکسی در مسابقه حدس زدن کلمه انگلیسی اینستاگرامی شرکت می کنه

یک اکانت اینستاگرام که نمی دونم کی فالوش کردم مسابقه جمعه‌ها برگزار کرده:

Screenshot_2015-04-17-14-35-43

موضوع مسابقه پیدا کردن یک کلمه ده حرفی است که مربوط به این شکل باشه و ده حرفی باشه و در جاهای مشخص شده a‌ و q نشسته باشن.

بریم برای جواب؟ در لینوکس بسته scowl‌ رو می‌شناسم (یا با سرچ بهش می رسم) که بقیه غلط‌یاب‌های دیکته ازش استفاده می کنن. این بسته حاوی کلی فایل است که همه کلمات زبان‌ انگلیسی توشه (از آمریکا تا کانادا و دستاشون).

نصبش می کنیم:

jadi@funlife:/tmp$ sudo aptitude install scowl 
[sudo] password for jadi: 
The following NEW packages will be installed:
  scowl 
0 packages upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 2,249 kB of archives. After unpacking 7,516 kB will be used.
Get: 1 http://ir.archive.ubuntu.com/ubuntu/ utopic/universe scowl all 7.1-1 [2,249 kB]
Fetched 2,249 kB in 9s (248 kB/s)                                               
Selecting previously unselected package scowl.
(Reading database ... 639459 files and directories currently installed.)
Preparing to unpack .../archives/scowl_7.1-1_all.deb ...
Unpacking scowl (7.1-1) ...
Processing triggers for cracklib-runtime (2.9.1-1build1) ...

و به دایرکتوری اش می ریم. چون برنامه اجرایی نیست و تنظیمات و موقت هم نیست منطقا باید راحت در usr/share بشه پیداش کرد.

jadi@funlife:/usr/share/dict/scowl$ cd /usr/share/dict/scowl/

حالا یک نگاه بندازیم ببینیم چه تیپ چیزهایی داریم اینجا:

jadi@funlife:/usr/share/dict/scowl$ ls -ltrh | tail
-rw-r--r-- 1 root root  13K Oct 23  2011 special-hacker.50
-rw-r--r-- 1 root root 2.4M Oct 23  2011 english-words.95
-rw-r--r-- 1 root root 238K Oct 23  2011 english-words.50
-rw-r--r-- 1 root root  34K Oct 23  2011 english-words.10
-rw-r--r-- 1 root root 787K Oct 23  2011 english-proper-names.95
-rw-r--r-- 1 root root  57K Oct 23  2011 british-words.80
-rw-r--r-- 1 root root  56K Oct 23  2011 american-words.80
-rw-r--r-- 1 root root  15K Oct 23  2011 american-words.70
-rw-r--r-- 1 root root 9.1K Oct 23  2011 american-words.50
-rw-r--r-- 1 root root  303 Oct 23  2011 american-words.10

و توی یکیشون رو به اتفاق نگاه می کنیم:

jadi@funlife:/usr/share/dict/scowl$ tail canadian-words.10
realized
realizes
realizing
recognize
recognized
recognizes
recognizing
rumour
spelled
storey

بعله. فایل های خودمون هستن.

حالا کار راحته: گشتن در همه فایل ها و پیدا کردن چیزی که ترکیب مورد نظر اونها رو داشته باشه. دقت کنیم که در egrep، علامت نقطه یعنی «هرکاراکتری»… علامت ^ یعنی اول خط و علاقمت $ یعنی آخر خط. پس:

jadi@funlife:/usr/share/dict/scowl$ egrep "^a...q.....$" *
english-words.35:antiquated
english-words.35:antiquates
english-words.80:antiquarks
english-words.95:ablaqueate
english-words.95:alfaquin's
english-words.95:antiquer's

یوهاهاها… دو تا آخری که جذاب نیستن. آنتی کوارک که می دونیم چیه، ablaqueate رو توی گوگل سرچ کردم مهم نبود پس جواب ما antiquated است که یعنی کهنه و منسوخ و خارج از مد. جواب رو دادم و منتظرم ببینم چی می‌گن.


آپدیت: نوید راد پیشنهاد می ده به دلیل نبودن بسته اسکاول در اکثر توزیع ها کد زیر رو هم بذارم:

curl -O -J -L http://sourceforge.net/projects/wordlist/files/latest/download?source=typ_redirect
tar -xvf ./scowl-yyyy.mm.dd.tar.gz # say, scowl-2015.02.15.tar.gz
cd scowl-2015.02.15/final
grep -Ea "^a.{3}q.{5}$" *

بخش اول که دانلود کردن اسکاول از منبعش در سورس فورج است و خط آخر همون رجکس من که کمی بهتر / کمتر خوانا نوشته شده و عوضش یک چیز جدید به شما یاد می ده اگر درست نگاهش کنین:‌ روش اینکه بگیم «از همین قبلی سه تا».