سیر صعودی $ و روش‌های مختلفی که برای دانلود در لینوکس یاد گرفتم!

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

Konqueror:

خوب اولین ابزار دم دستمان مرورگر پیش‌فرض KDE است‌. برای دیدن فایل‌های روی وب‌سرور تنها کافیست در آدرس‌بار چنین چیزی بنویسیم:

fish:[email protected]

خودش پس از شروع به جستجو پسوورد می‌پرسد که همان پسوورد ssh (پسوورد یوزر) خواهد بود‌. و دیگر می‌توانید با فایل‌ها جوری رفتار کنید که انگار روی کامپیوتر خودتان قرار دارند‌. ولی خوب بدیهی است که با سرعت اینترنت بالای ما‌، خیلی دردناک است‌. برای فایل‌های کوچک حداکثر تا دو سه مگابایتی می‌توان با یک کپی پیست ساده سر و ته قضیه را هم آورد‌. ولی اگر فایل دو گیگ باشد‌، باید دنبال چارهٔ بهتر گشت‌.

scp

یا همان Safe CoPy‌، که به این صورت مورد استعمال قرار می‌گیرد:

scp [email protected]:PATH_TO_FILE _Path_to_download_

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

scp خوب است‌، ولی باز هم زیاد به درد موقعیت ما نمی‌خورد‌. می‌رویم گزینهٔ بعدی.

Filezilla

این فایلزیلای پدر سوخته را احتمالا از روی استفاده‌هایش برای FTP می‌شناسید‌. خوب خوشبختانه این‌ها از پروتکلی به اسم SFTP هم پشتیبانی می‌کنند که منظورش این است که SSH می‌تواند برای وصل شدن به سرور مقصد قرار گیرد‌. پس کافیست از منوی فایل روی Site manager کلیک کنید و صفحهٔ باز شده را مثل عکس زیر کانفیگ کنید:

Filezilla site manager

و بعد هم روی connect بزنید و تمام‌. خیلی راحت وصل می‌شوید و می‌توانید با Drog & Drop فایل را انتقال دهید به سیستم‌تان‌. آسان بود‌. ولی خوب ما فقیر فقرا که ساعت ۲ تا ۷ صبح سرعت اینترنت‌مان سر به فلک می‌کشد‌، با تک نخی بودن مدل دانلود‌مان احتمالا طی پنج ساعت نمی‌توانیم ۲ درصد یک فایل دو گیگی را دانلود کنیم‌. می‌توانیم؟

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

rsync

یاد‌تان می‌آید گفتیم که scp سرعت خوبی داشت ولی Resume نمی‌کرد‌. یک ابزار دیگر هم داریم که جینگولک بازی‌هایش در زمان Resume فوق‌العاده است و زبان زد خاص و عام‌. مثل این نقل قول:

ای کسانی که ویندوز آورده‌اید‌، اگر راست می‌گویید rsync بیاورید «منبع نامعلوم منبع خودش اومد اعتراف کرد ;-)»

این می‌شود که از آن به صورت زیر استفاده می‌کنیم:

rsync -az --progress --rsh='ssh' --partial [email protected]:PATH_TO_FILE _Path_to_download

خیلی هم خوب‌. یکی از ویژگی‌هایش این است که می‌توانید آدرس یک پوشه را برای دانلود بهش بخورانید و دیگر دست به دستور نزنید و فقط هر وقت خواستید رانش کنید‌. خودش آخرین فایل‌های آن پوشه را می‌گیرد‌. اما امان از سرعت‌. این جینگولک بازی‌های rsync روی قابلیت‌های فوق‌العاده resume‌اش هزینه دارد و آن هم سرعت است‌! که ما به آن هم خیلی نیاز داریم‌. برای این کار بسته به موقعیت می‌توانیم آن آرگومان z را حذف کنیم‌. ولی حقیقتش برای ما فرق چندانی نداشت‌.

این است که rsync هم می‌گذاریم برای وقتی که لازمش داریم و می‌رویم دنبال یک راه حل بهتر که هم Resume کند‌، هم چند نخه دانلود کند‌، و از آن مهم‌تر این که هی مجبورمان نکند پسوورد بزنیم! آخر چه کسی حالش را دارد ساعت ۲ صبح پسوورد یادش بیاورد؟

lftp

فوق‌العاده‌ است‌. فوق‌العاده‌. و این‌طوری استفاده می‌شود:

lftp -c "mirror -c --use-pget-n=10 --verbose sftp://USER:[email protected]/PATH_TO_FILE"

هوم‌، یک کمی طولانی شد‌. ولی بگذارید کمی در موردش صحبت کنیم‌. چون واقعا لازم به توضیح است:

  • ‎-c اول یعنی این که دستور روبرو را اجرا کن‌.
  • mirror یک برنامه توکار برای lftp است‌. یکی دیگر مثلا pget است‌. هر کدام به درد جایی می‌خورد و این mirror الان به درد ما‌. (از pget هم می‌توان استفاده کرد ولی این یکی بیشتر به مزاقم نشست).
  • ‎-c این آرگومان مال mirror است و یعنی Resume کن اگر می‌توانی D:
  • ‎--user-pget-n=10 یعنی فایل را ده قسمت کن و همه را با هم بگیر‌. این همان قابلیت چند نخی است که باعث افزایش سرعت می‌شود و دانلود منیجر‌های مدرن با آن پز می‌دهند ;-)
  • USER:PASSWORD یعنی این‌ور یوزر را می‌نویسیم و آن‌ورش رمز عبورش را!
  • PATH_TO_FILE این‌بار کمی با باقی مواقع فرق دارد‌. قبلا آدرس را از پوشهٔ خانگی یوزری که وارد شده بود وارد می‌کردیم و موضوع حل بود‌. ولی اینجا آدرس را از ریشه (/) می‌نویسیم‌. یعنی اگر در پوشهٔ خانگی‌تان است می‌شود این:
/home/USER/File

lftp هم مانند rsync (شاید هم scp) زورش را دارد که پوشه‌ای که به آن خورانده‌ایم را دانلود کند‌.

همین دیگر‌. دیدید؟ باز هم بگویید بد است‌. لامصب را می‌بینید که چقدر به فکر جیب آدم است؟ با هر پولی و با هر سازی که دلتان خواست برایش بنوازید‌، برای‌تان آن‌قدر خوب رقص می‌کند که انگشت به دهن می‌بانید ;-)

Dunst اطلاع رسان کوچک برای مدیر‌پنجره‌های سبک مثل i3 یا DWM

نمونه xfce4-notifydجدای از این هم به دلیل قابل کنترل نبودن با کیبورد‌، زیاد به مزاقم خوش نمی‌آمد‌. این شد که امروز چرخی زدم و با Dunst آشنا شدم‌ که خودش را این‌طوری معرفی می‌کند:

dunst - dmenu-ish notification daemon

و خوب از آن‌جایی که Dmenu بخش حیاتی زندگی‌مان در i3 شده‌، احتمالا Dunst هم می‌تواند انتخاب خوبی باشد‌. خصوصا با همچین اسکرین‌شاتی که معلوم می‌شود ظاهری بسیار شبیه به Dmenu دارد‌:

نمونه dunstبرای نصبش کار سختی پیش رو ندارید‌. جز این که اول notification daemon‌ای که قبلا استفاده می‌کردید (روی اسلکور xfce4-notify) را پاک کنید و حالا بسته به توزیع‌تان با مخازن‌تان بگیرید و یا با دو دستور (که در صفحهٔ اصلی پروژه نوشته شده) نصبش کنید‌.

بعد از نصب هم با دستور زیر:

cp /usr/share/dunst/dunstrc ~/.config

یک نمونه از فایل تنظیمات را در پوشهٔ خانگی‌تان کپی کنید‌. از من می‌شنوید چرخی در این فایل بزنید چون تنظیمات خیلی به درد بخوری در آن پیدا می‌کنید‌ (ضمن این که ظاهر اولیه اصلا شباهتی به Dmenu ندارد ;-))

اما بیشترین نقاط قوت این اطلاع رسان ساده در میانبر‌های کیبوردش مخفی شده به طوری که:

  • می‌توانید با Ctrl+Space اخطاری را که روی صفحه ظاهر شده قبل از به پایان رسیدن تایمش ببندید‌.
  • می‌توانید با Ctrl+grave آخرین اخطاری که ظاهر شد و شما ندید را به روی صفحه برگردانید (که به نظرم خیلی به درد بخور است). grave همان دکمه‌ای است که باهاش ~ تایپ می‌کنید‌. کنار ۱ و بالای TAB ;-)
  • یا اگر زیر بار حملهٔ Notificationها در حال له شدنید با Ctrl+Shift+Space با یک تیر همه را قتل عامل کنید ;-)

نکته ۱: برای ایجاد یک Notification می‌توانید از دستور زیر استفاده کنید:

notify-send Test

که جای Test هر چیزی که خواستید می‌توانید به عنوان پیغام اضافه کنید‌.

نکته ۲: Dunst تنها قبل از اجرای daemon‌ش فایل کانفیگی که در ‎.config ذخیره کردیم را می‌خواند‌. برای دیدن تغییرات باید اول این daemon را kill کنید و دوباره اجرایش کنید ;-)

نسخهٔ جدید ویرایشگر متن نگار

برای بزرگ شدن تصویر روی آن کلیک کنید.

قابلیت‌هایی که نسبت به نسخهٔ قبلی به آن اضافه شده عبارتند از:

  • قابلیت جدا کردن کلمات نوشته شده به صورت «‌میشود‌».
  • اضافه کردن نیم فاصله بعد از پرانتز (یا علامت‌هایی نظیر آن) که باعث می‌شود کلمه جدا از آن کاراکتر دیده شود که مزیت‌های خودش را دارد‌.
  • رابط گرافیکی نوشته شده بر مبنای PyQt4.
  • پردازش بهتر آرگومان‌های خط فرمان.
  • قابلیت تنظیم آپشن‌ها از طریق خط فرمان.

فعلا چیز دیگری یادم نمی‌آید‌. برای نصب هم اول مطمئن شوید که PyQt4 و setuptools را با توجه به توزیع‌تان نصب کرده‌اید‌، سپس با استفاده از سه دستور زیر‌، کار را تمام کنید:

$ git clone https://github.com/shahinism/Negar.git

$ cd Negar

$ sudo python setup.py install

یک نکته هم در مورد قابلیت جدا کردن کلمات و نحوهٔ کارش اضافه کنم‌. خوب اگر ما همانطور که فاصله‌ها را کنترل می‌کنیم‌، (یعنی با regular expression) می‌خواستیم این کلمات مانند «میشود‌، کمکتان» و… را جدا می‌کردیم‌، در مورد کلماتی مانند «میلاد» به مشکل بر می‌خوردیم‌. برای کنترل چنین وضعیتی از فایلی به اصم untouchable.dat که شامل کلماتی از این دست می‌شود (فایل را از روی یک دیکشنری در پروژهٔ ویراستیار و با کمک چند اسکریپت سریع تولید کرده‌ام و هنوز جای کار بسیاری دارد) استفاده کرده‌ام‌. کاربر می‌تواند کلماتی از این دست که نگار در موردشان درست اقدام نمی‌کند را با استفاده از رابط گرافیکی و یا کنسول به این لیست اضافه کند‌.

پی‌نوشت ۱: در معرفی قبلی‌، اشتباهی در مورد اسکرین‌شات کردم و بررسی نکرده منتشرش کردم که متاسفانه‌، باعث سوء تفاهم‌هایی شد که از همین تریبون عذر خواهی می‌کنم ;-)

پی‌نوشت ۲: دوست عزیزی به اسم رامین‌، پروژه را فورک و چند ویرایش خوب روی سورس انجام داد که از آن‌هایی که می‌توانستم (با توجه به این که سورس را دوباره از نو نوشتم) استفاده کردم‌. اما متاسفانه احساس می‌کنم ایشان از رفتارم سوء برداشت کرده‌اند‌. به هر حال از ایشان عذر خواهی می‌کنم و امید‌وارم مرا ببخشند‌.

پی‌نوشت ۳: همین دوست عزیز یک نسخهٔ گرافیکی دیگر بر مبنای سورس (که بعضی امکانات این نسخه را ندارد) قبلی نگار توسعه داده که قابلیت غلط گیر املایی هم به آن افزوده شده‌. جالب است‌، تستش کنید ;-)

راهنمای کوتاه کار با DBus در پایتون (نوشتن روبات پاسخگو برای Pidgin)

بعد از کمی جستجو‌، با DBus آشنا شدم و البته یادم آمد که خیلی وقت پیش‌، جادی عزیز‌، کاری تقریبا در همین مایه‌ها با DBus و Pidgin انجام داده بود‌. توضیحات تکمیلی در مورد DBus را می‌توانید در وبلاگ جادی بخوانید‌، خصوصا این که اسکریپت نوشته شده توسط جادی در آن پست‌، پیش در آمد خوبی برای این کار است‌، و حقیقتش تنها منبع به درد بخورم در این زمینه بود‌! (منظورم در زمینهٔ عملی کار با DBus است‌، در زمینهٔ تئوری و به عنوان یک راهنما می‌توان به راهنمای Freedesktop بسنده کرد‌.)

مساله این‌جاست که می‌خواهیم اسکریپتی بنویسیم که پس از اجرا‌، منتظر Pidgin بماند‌. اگر Pidgin پیغامی دریافت کرد‌، اسکریپت به صورت خود‌کار و بلافاصله‌، جوابی را که از قبل بهش خورانده‌ایم رو به مخاطب آن‌ور خط بدهد‌.

با این وصف‌، اسکریپت‌مان دو مرحله خواهد داشت‌.

اول‌، منتظر ماندن برای یک علامت که از طرف Pidgin‌، پس از دریافت پیام ارسال می‌شود‌.

دوم‌، ارسال جواب برای مخاطبی که پیغام را ارسال کرده‌.

برای انجام این کار اول از همه‌، ابزار‌های مورد نیازمان را وارد می‌کنیم‌:

[python]

import sys

import dbus

from PyQt4.QtGui import QApplication

from dbus.mainloop.qt import DBusQtMainLoop

[/python]

قرار بر این بود که اسکریپت پس از اجرا منتظر بماند‌، درست؟ خوب همان‌طور که می‌دانید برنامه‌ها منطقا جوری نوشته می‌شوند که یک کاری را شروع کنند‌، انجام دهند‌، و پایان یابند‌. این روند زیاد برای کار ما مناسب نیست‌. از طرفی استفاده از حلقه‌های بی‌نهایت مرسوم‌‌، جز پیچیده کردن کار‌، نتیجه‌ای به همراه ندارد‌. این است که برای سازگاری بیشتر اسکریپت با برنامه‌های Qt (در ادامه دلیلش را می‌گویم) از QApplication و DBusQtMainLoop برای مدیریت حلقهٔ اصلی استفاده می‌کنیم‌. در ادامه اضافه می‌کنیم:

[python]

bus_loop = DBusQtMainLoop(set_as_default=True)

[/python]

کار با حلقهٔ اصلی هنوز تمام نشده‌، باقی کار را آخر انجام می‌دهیم‌. و اما حالا نوبت به انجام مرحلهٔ اول کارمان می‌رسد. تابع گیرندهٔ سیگنال (همان علامتی که Pidgin پس از دریافت پیغام ارسال می‌کند) را می‌نویسیم‌.

[python]

def connect_dbus(text):

global answer

answer = text

bus = dbus.SessionBus()

bus.add_signal_receiver(pidgin_control_func,

dbus_interface="im.pidgin.purple.PurpleInterface",

signal_name="ReceivedImMsg")

[/python]

اولین سوال در این تابع‌، این است که به کدام DBus وصل شویم؟ به طور معمول دو DBus داریم‌، SystemBus که به صورت سراسری (System wide) است‌‌. و دومی SessionBus که محدود به یوزر اجرا کنندهٔ برنامه می‌شود‌. برای کار ما‌، دومی‌، انتخاب معقول‌تری است‌. پس از اتصال‌، نوبت به نصب یک پیغام‌گیر می‌شود‌. تابع مورد استفاده به صورت bus.add_signal_receiver است که سه آرگومان می‌گیرد‌. که هر کدام به سوالی پاسخ می‌دهند‌:

۱- پس از دریافت سیگنال کدام تابع را صدا کنم؟ پاسخ: pidgin_control_func (تابعی که در مرحلهٔ دوم خواهیم ساخت)

۲- روی DBus به حرف کدام برنامه گوش کنم؟ پاسخ: Pidign که خوب ما از آدرس DBusاش برای معرفی استفاده می‌کنیم‌.

۳- منتظر چه نوع علامتی باشم؟ پاسخ: ReceivedImMsg که با کمی جستجو در مستندات Pidgin به عنوان علامت دریافت پیغام توسط Pidgin شناسایی کردیم ;-)

در این تابع ما از فراخوان می‌خواهیم که آرگومانی را به عنوان text برایمان ارسال کند و آن را به متغیر سراسری answer نسبت می‌دهیم‌. دلیل این کار ساده است‌. چون می‌خواهیم کلا در برنامهٔ اصلی فقط همین تابع را صدا کنیم و خودش باقی کار‌ها را انجام دهد.

نوبت به نوشتن تابع دوم می‌رسد‌:

[python]

def pidgin_control_func(account, sender, message, conversation, flags):

bus = dbus.SessionBus()

obj = bus.get_object("im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")

purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")

if purple.PurpleAccountGetUsername(account) != sender:

purple.PurpleConvImSend(purple.PurpleConvIm(conversation), answer)

[/python]

خوب اول از همه این که ما در نوشتن این تابع ۶ آرگومان می‌گیریم‌. و البته این شش آرگومان چیز‌هایی هستند که همان سیگنال ReceivedImMsg برای‌مان می‌فرستد‌. که البته اطلاعات خیلی به درد بخوری‌اند‌. طبق روال قبلی به SessionBus وصل می‌شویم (این کار را می‌شد یک بار انجام داد‌، ولی موقع استفاده به صورت ماژول کمی جفتک می‌انداخت). در ادامه به سه سوال دیگر جواب می‌دهیم:

۱- روی DBus به کدام برنامه گوش کنم؟ پاسخ im.pigin.purple.PurpleService

۲- آدرسش کجاست؟ پاسخ: ‎/im/pidgin/purple/PurpleObject

در واقع با پاسخ به این دو سوال‌، سعی به ساخت یک شیع ارتباطی با برنامهٔ مورد نظر داریم‌. حال با این شیع می‌توانیم یک رابط برای مکاتبهٔ تابع‌مان با Pidgin بسازیم‌.

۳- کدام رابط از آبجکت ساخته شده؟ پاسخ: im.pidgin.purple.PurpleInterface

و خوب حالا تنها برای ارسال پیام کافی است تابع PurpleConvImSend را از شیع ساخته شده صدا کنیم‌ و به دو سوال پاسخ دهیم:

۱- به چه کسی پیغام بفرستم؟ پاسخ: کسی که برای‌مان پیغام فرستاده‌. برای به دست آوردنش کافی است که از تابع PurpleConvIm از شیع‌مان بخواهم که آدرسش را پیدا کند ;-)

۲- چه بگویم؟ پاسخ answer‌‌، همان متغیر سراسری که که در تابع اول‌، مقدار دهی‌اش کردیم‌.

البته من در تابع یک قفل کودک هم گذاشته‌ام‌. چطور؟ ماجرا این‌جاست که با نوشتن هم‌چین تابعی‌، وقتی وسوسه می‌شوید که خود‌تان امتحانش کنید‌، به یک لوپ بی‌نهایت تبدیلش می‌کنید! کافیسیت برای دیدن این لوپ شرط if موجود در تابع را پاک کرده و تابع را امتحان کنید‌. یک بار به خود‌تان پیغام بدهید‌، Pidgin علامت می‌دهد‌، روبات پاسخ می‌دهد و دوباره پس از دریافت پیغام روبات روی Pidgin‌، این برنامه دوباره سیگنال ارسال می‌کند و این کار اگر ولش کنید تا عبد ادامه خواهد داشت ;-)

دیگر وقت اجرای تابع اصلی رسیده‌، و کافیست که:

[python]

app = QApplication([])

connect_dbus(message)

app.exec_()

[/python]

برنامه الان به راحتی اجرا می‌شود و کاری را هم که می‌خواهیم دقیقا انجام می‌دهد(البته طبیعی است که چیز‌های ساده‌ای باید به آن اضافه کنید‌.)‌. ولی هنوز یک مشکل دارد‌، آن هم این که نمی‌توان آن را بست‌! حتی Ctrl+c هم در ترمینال آن را نمی‌کشد‌. این است که از دو خط زیر و دقیقا قبل از ساختن شیع app کمک می‌گیریم:

[python]

import signal

signal.signal(signal.SIGINT, signal.SIG_DFL)

[/python]

کار این تابع این است که وقتی SIGINT یا همان Ctrl+c ما را گرفت (توجه کنید که این کلید در رابط گرافیکی Qt برای کپی متن استفاده می‌شود) آن را به SIG_DFL ترجمه کند‌! یعنی بزند بترکاند برنامه‌مان را ;-)

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

python answering_machine.py ANSWER_MESSAGE

اما خوب درست است که این اسکریپت تقریبا مشکل‌مان را حل می‌کند‌، اما هنوز یک جای کارش می‌لنگد‌! باز هم من کم حواس باید یادم باشد که اجرایش کنم‌! و از آن بد‌تر در وقت آزادم خاموشش کنم‌! و این اصلا حال نمی‌دهد‌. این است که آن را با PyPomo قاطی می‌کنم‌ (آخرین نسخهٔ روی گیت). جوری که وقتی در حال انجام یک پامودور هستم‌، این اسکریپت را روشن کند‌، و وقتی که موقع استراحت است یا interrupt داده‌ام‌، آن را خاموش کند‌. حالا دیگر تقریبا همه چیز حل شده است ;-)

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

پی‌نوشت۲: می‌دانم برنامه به بهترین شکل ممکن نوشته نشده‌، زیاده کاری دارد و حتی در ترکیبش با PyPomo باگ‌هایی هست که به چشمم نیامده‌، ولی خوب حداقل تلاشم را کرده‌ام دیگر‌. اگر برنامه نظرتان را جلب کرده‌، و راه بهتری بلدید‌، روی گیت فورکش کنید و تغییرات‌تان را اعمال کنید‌. مطمئنم چیز‌های بهتری می‌توان ازش ساخت‌!

اسکریپتی برای کاهش هزینهٔ شرکت در کلاس‌های دانشگاه Coursera

زیاده‌گویی بس است‌. خیلی وقت پیش هم در کلاس‌های این سایت شرکت کرده بودم‌، ولی ادامه ندادم‌. چرا؟ حقیقتش مجموعهٔ دانلودی‌اش عالی است‌. فیلم آموزشی‌، زیرنویسش‌، اسلاید و …. اما خودتان که می‌دانید زندگی سایبری (‌حالم از این کلمهٔ آخر به هم می‌خورد‌، جایگزین بهتری نمی‌شناسید؟) در ایران‌، خصوصا با این کیفیت عالی (!) چه هزینهٔ گزافی دارد‌. این شد که دیروز وقتی دوباره لیست این کلاس‌ها‌، وسوسه به مطالعه‌شان را در من تقویت کرد‌، تصمیم به دانلودشان به صورت شبانه گرفتم‌. اما مشکل این‌جاست که باید شب را تا صبح پای کامپیوتر بگذرانم و تک به تک دانلودشان کنم‌، چرا که‌، پروسهٔ دانلود سایت کمی قرتی تشریف دارد و کوکی می‌خواهد‌. قصد داشتم برای چالش هم که شده یک اسکریپت برای این کار بنویسم‌.

اما خوشبختانه بعد از اولین جستجو به کامل‌ترین نسخهٔ ممکن برای این کار رسیدم‌. اسکریپتی که دیروز کار نمی‌کرد‌، و باعث شده بود تصمیم بگیرم تعمیرش کنم‌، ولی باز توسعه دهندهٔ خوش‌فکرش به کارش انداخت و الان مثل چـــی کار می‌کند ;-)

مزیتش نسبت به تمام روش‌های دانلود دیگر این است که فقط کافیست نام کلاس را بهش بگویید و خودش همه چیز‌های مربوطه را برایتان دانلود کرده‌، نام درست را برای‌شان بگذارد و در پوشه‌های جدا دسته بندی می‌کند‌. (هلو …؟)

اول با توجه به توزیع زیر دستتان‌، بستهٔ setuptools از خانوادهٔ پایتون را نصب کنید‌، و باقی کار را مثل زیر انجام دهید:

easy_install BeautifulSoup

easy_install argparse

git clone https://github.com/jplehmann/coursera.git

cd coursera

و حالا با چنین نحوی می‌توانید دانلود را انجام دهید:

./coursera CLASS_NAME -u USER_NAME -p PASSWORD

برای به دست آوردن CLASS_NAME صفحهٔ کلاس مربوطه را در سایت باز کنید‌. مثلا برای Algorithms 1 همچین چیزی است:

https://class.coursera.org/algs4partI-2012-001/lecture/index

آن بند algs4partI-2012-001 می‌شود نام کلاس‌ الگوریتم‌ها‌. جایش در باقی کلاس‌ها یکسان و معلوم است ;-)

پی‌نوشت: در آیندهٔ نزدیک یک روش گاز‌انبری و خیلی دم دستی را یادتان می‌دهم که می‌تواند این کوکی‌های کذایی را دور بزند.