میخواهیم یک فایل HTML را پردازش کرده و همچنین اطلاعاتی را از آن استخراج کنیم. برای این کار، باید کلاسی به نام HTMLParser طراحی کنید که ویژگیها و توابع زیر را دارا باشد:
class HTMLParser:
    def __init__(self, html_doc):
        self.html_doc = html_doc
        pass
    def set_html_doc(self, html_doc):
        self.html_doc = html_doc
    def find_first(self, output_arg, **finding_args):
        pass
    def find_all(self, n, output_arg, **finding_args):
        pass
    def find_parent(self, output_arg, **finding_args):
        pass
    def find_grandparent(self, n, output_arg, **finding_args):
        pass
    def remove_comment(self, **finding_args):
        pass
    def remove_all_comments(self):
        pass
    def remove_tag(self, **finding_args):
        pass
if __name__ == '__main__':
    pass
پیش از شرح توابع و ویژگیها، مشخصههای جستجو finding_args و مشخصهٔ خروجی output_arg را شرح میدهیم:
مشخصههای جستجو (finding_args)
finding_args)یک دیکشنری است که میتواند یک یا چند کلید از میان name ،  id ، string و class بپذیرد. برای مثال برای تگی مانند مثال زیر:
<p class="important" id="some-ID">you can <i>access</i> Quera <a href="http://www.quera.ir">here</a>!</p>
مشخصهٔ name برابر p، مشخصهٔ id برابر some-ID، مشخصهٔ string برابر you can access Quera here! و مشخصهٔ class برابر important میباشد. تضمین میشود مشخصههای جستجوی ورودی تنها شامل مشخصههای فوق میباشد.
مشخصهٔ خروجی (output_arg)
output_arg)یک str است که مشخصهٔ مطلوب خروجی تابع را مشخص میکند و تضمین میشود مقادیری همانند بالا دارد. در صورتی که مقدار متناظر مشخصهٔ خروجی مقداردهی نشده بود، خروجی یک رشتهٔ خالی خواهد بود.
parser = HTMLParser("<b>some text.</b>")
>>> parser.find_first("class", name='b')
""
>>> parser.find_first("string", name='b')
"some text."
>>> parser.find_first("name", string="some text.")
'b' 
نمونه
برای مثال فراخوانی یک تابع با مشخصههای فوق، چنین است:
parser.find_first("string", id="link", name='a')
ویژگیها و توابع این کلاس به شرح زیر هستند:
ویژگی html_doc
کل کد html_docHTML به فرمت یک رشته str است.
متد find_first
مقدار مشخصهٔ خروجی (find_firstoutput_arg) اولین برچسب که با ویژگیهای finding_args مطابقت داشته باشد را خروجی میدهد.
متد find_all
یک لیست به طول حداکثر find_alln از مقدار مشخصههای خروجی برچسبهای مطابق با finding_args را برمیگرداند (nتای اول).  اگر تعداد برچسبهای یافتهشده کمتر از n بود لیستی به اندازهٔ همان تعداد برمیگرداند.
مثال:
doc = '<b id="1">first</b> <b id="2">second</b> <b>third</b>'
parser.set_html_doc(doc)
>>> parser.find_all(4, "id", name='b')
['1','2',""]
متد find_parent
مقدار مشخصهٔ خروجی اولین والد برچسب مطابق با مشخصههای جستجو را خروجی میدهد. (در صورتی که بیش از یک برچسب یافت شد، مقدار مطلوب را برای اولین برچسب یافتهشده خروجی میدهد.) تضمین میشود برچسبهای یافتهشده حداقل یک والد دارند.
find_parentمثال: 
parser.set_html_doc("<p><b>example</b></p>")
>>>parser.find_parent("name", name='b', string='example')
'p'
متد find_grandparent
مقدار مشخصهٔ خروجی find_grandparentnاُمین جد (اولین جد همان والد است.) اولین برچسب مطابق با مشخصههای جستجو را خروجی میدهد. در صورتی که n از تعداد جدهای برچسب یافته شده بیشتر باشد، استثنایی با پیام No Such Parent پرتاب شود. تضمین میشود برچسبهای یافتهشده حداقل یک والد دارند.
متد remove_comment
اولین برچسب منطبق با مشخصهٔ ورودی را در صورتی که فقط محتوی کامنت باشد به طور کلی از remove_commenthtml_docحذف میکند. کامنتهای HTML به صورت زیر هستند:
<!--Some Comments-->
parser.set_html_doc('<b id="comment"><!--comment--></b>')
>>> parser.remove_comment(name='b')
>>> parser.html_doc
""
>>> parser.set_html_doc("<b>not a <!--comment--></b>")
>>> parser.remove_comment(name='b')
>>>parser.html_doc
"<b>not a <!--comment--></b>"
در صورتی که محتویات اولین برچسب یافتهشده عاری از کامنت بود، استثایی با پیام No Comments Found پرتاب شود.
متد remove_all_comments
تمامی برچسبهای محتوی کامنت را از remove_all_commentshtml_doc حذف میکند.
متد remove_tag
اولین برچسب مطابق با مشخصات ورودی را به طور کلی از remove_taghtml_doc حذف میکند.
توجه: در تمامی متدهایی که میبایست برچسبی مطابق با مشخصات ورودی یافت شود، اگر برچسبی یافت نشد باید استثنایی با پیام No Such Tag  پرتاب شود.
نکات
- میتوانید فایل اولیه این سوال را از این لینک دریافت کنید.
 - دقت کنید که در هیچکدام از توابع نباید مقداری را چاپ کنید؛ تنها در توابعی که گفته شده مقداری را بازگردانید، باید مقدار مورد نظر را 
returnکنید. 
نحوه ارسال
فایل کامل شده HTMLParser.py را ارسال کنید؛ همچنین برای استفاده از کتابخانههای مختلف میتوانید همراه فایل ارسالی، فایلی به نام python_requirements.txt در ZIP خود بگذارید که در آن نام کتابخانههای مورد نیاز و شماره نسخهی آنها به فرمت زیر در آن موجود باشد: (اگر شماره نسخه را ننویسید آخرین نسخهی آن کتابخانه نصب میشود)
firstlib==1.2.3
secondlib==4.5.6
...
در نهایت یک فایل ZIP حاوی دو فایل خواسته شده را آپلود کنید.
ارسال پاسخ برای این سؤال