skip to Main Content

Context

I have been doing this small web scraping project to practice and polish my coding skills. I had an idea that I could preserve some of my grandpa’s work and save it somewhere and keep up his legacy in the future when it doesn’t exist anymore on the site. So I’m doing my part where I can do what I can and share it with my family.

I’m using Python to do this project and using urllib without the use of other frameworks like BeautifulSoup or Selenium. The reason I’m doing this is to have a strong principle in coding in general, and slowly build up to the best way and the reasons behind it. Plus, I want to learn my libraries too, so I believe this is a good way to learn in general. Eventually (not now, though), I will opt-in to a BeautifulSoup in a different project.

Problem

I have a parser that checks for paragraphs and saves them into a list. So whenever there is a <p> and </p>, I would put the information inside of my list and continue. Now, I do this for every title it finds, but I found a small bug for a specific type of articles. When the article has a <font> and </font> compared to the other ones, they are differently structured. I’m trying to check for the font tags, but it seems it is not doing the work as it is supposed to do. For all this, I do inspect element to whatever div is located, and just parse from it.

Example

This is my initial URL, I parse from the div it starts (div class="item-article-body size-20") that the is located, and go from there.

<div class="item-article-body size-20">
<div class="author-image">
<a href="https://alrai.com/author/19/د-زيد-حمزة">
<img src="https://alrai.com/uploads/authors/19_1635945465.jpg" width="100%" height="100%" alt="د. زيد حمزة">
</a>
</div>
<a href="د. زيد حمزة" class="author-name-a">د. زيد حمزة</a>
لم يكن ضروريا أن ينتظر الشعب البريطاني وغيره من شعوب العالم سبع سنوات حتى يطل عليها تقرير تشيلكوت ويدين توني بلير فالادانة الشعبية – ولو على نطاق محدود – كانت قائمة حتى قبل الحرب على العراق، ولم يكن ضروريا أن يقرأ الناس في كل مكان آلاف الصفحات كي يستوعبوا حجم الخديعة التي أجاد نسج خيوطها رئيس الوزراء البريطاني بالتواطؤ مع رئيس الولايات المتحدة لتبرير تلك الحرب التي اودت بحياة الآلاف من جنود بلديهما وبلغت تكاليفها ارقاما فلكية (اكثر من 3 تريليون دولار) ! كما لم يُرضِ احداً ان يسارع بلير في اليوم التالي لصدور التقرير بمواجهة الصحافة فيعترف بالخطأ لكنه يصر على أنه لولا غزو العراق لكان العالم الآن في حال أسوأ مع ان الواقع الماثل عكس ذلك تماما ومن مضاعفاته أن الارهاب الاعمى قد وصل الى الغرب نفسه ! لا بل إن بلير أهان الضمير العالمي حين لم يعترف بالذنب او يعتذر – مجرد اعتذار – عن التسبب في قتل وتشريد ملايين العراقيين وتدمير دولتهم وتمزيق بلدهم وإشعال فتنة طائفية فيها لا يعلم احد متى تنطفئ نارها.<br><br>صحيح أن لغة التقرير ليست جازمة في تبيان الأدلة على دخول حرب فتاكة بمبررات غير صحيحة على الاطلاق، فلا العراق كان يملك أسلحة دمار شامل ولا صدام كانت له علاقة بالقاعدة أو بن لادن، لذلك لم نجد وزارة العدل البريطانية تتحرك لاقامة الدعوى ضد توني بلير لمحاكمته امام القضاء البريطاني ولم تتحرك حكومة العراق (!) كي تأخذه الى محكمة العدل الدولية أو محكمة الجنايات الدولية كما وقفت مكتوفة اليدين منظمات حقوق الانسان ( أمنستي انترناشونال وهيومان رايتس ووتش على سبيل المثال ) وكذلك المفوضية الدولية لحقوق الانسان في الأمم المتحدة ! أما الديمقراطية البريطانية ، وهي أم الديمقراطيات كما يقال، فسوف يخجل برلمانها من عدم قدرته استنادا الى هذا التقرير على محاسبة توني بلير وتحميله مسؤولية الارواح ( ارواح الجنود البريطانيين على الأقل ) التي ازهقت عبثا وبهتانا رغم نصيحة المخابرات البريطانية بأن غزو العراق سوف لن يقضي على الارهاب بل يؤدي الى مزيد منه ورغم تقرير المخابرات الاميركية بناء على طلب من البنتاغون والذي أفاد ايضا بان الارهاب سوف يستشري ويتسع.. أما اللغة المائعة للتقرير - كما قالت كثير من الصحف العالمية – فربما كانت وراء تأخير صدوره كل هذه السنوات الطويلة ، في محاولة من قوى ضاغطة عديدة من اجل ان يأتي في صيغة تجعل رئيس الوزراء توني بلير قادراً على الافلات من العقاب وكذا الرئيس جورج دبليو بوش ونائبه ديك تشيني ووزير دفاعه دونالد رامسفيلد الذين استخدم بعض الكتاب في وصفهم نعوتاً جارحة وهم يتساءلون عن سبب حماسهم في شن الحرب على العراق الذي أنكر وجود اسلحة الدمار الشامل لديه في حين جبنوا كل الوقت عن التصدي لكوريا الشمالية التي تملك مثل هذه الاسلحة وتعلن عن وجودها في حوزتها ( حتى ان بعضهم ذكّر بباكستان! ) ، وقبل ذلك كله لم ينبسوا ببنت شفة وهم يعلمون علم اليقين بان اسرائيل تملك مائتي قنبلة ذرية على الاقل..! وقد سخر الكتاب كذلك من ادعاءات اولئك الزعماء الغربين بان الحرب كانت من اجل التخلص من دكتاتورية صدام وتوفير الديمقراطية للشعب العراقي فالعالم كله يعرف أن اكثر حلفائهم في المنطقة العربية لا يحكمون بالديمقراطية ! وأثبت بعض الكتاب ان هدف الحرب تدمير كيانات عديدة في المنطقة خدمة للحليفة الاستراتيجية اسرائيل وكان من نتائجها الكارثية ايضاً اقتتال طائفي وارهاب لم يعرف العالم مثيلاً لفظاعته..<br><br>وبعد.. فما لم تشر له معظم التعليقات هو أن المستفيد الأكبر من شن الحرب كان المجمع العسكري الصناعي من خلال البنتاغون وال <span dir="LTR">FED</span> وصفقات الأسلحة.. بالمليارات يومياً !<br><br>****<br><br>تنويه: أخطأتُ في مقال الاسبوع الماضي بان ذكرت أن المعابد البوذية تدعى بادوغا <span dir="LTR">Padoga</span> والصحيح أنها باغودا <span dir="LTR">Pagoda</span> ولقد لفت نظري لذلك الصديق حسان بدران (رفيق الرحلة الى بورما وفيتنام) وإذ أشكره فاني اعتذر للقراء وأعفي (الرأي) من مسؤوليتها عن هذا الخطأً..<br><br>
</div>

Code

import urllib.parse

def paragraphs(url):
#Note: if I want to look for paragraphs HTML elements, I would change it to <p> and </p> instead of font (that part works). Only issue is when it comes to the font and how the HTML is structured.

content = html_content(url)
paragraphs = []
target_element_paragraph_article = '<div class="item-article-body size-20">'
start_index = content.find(target_element_paragraph_article)

if start_index != -1:
    start_index += len(target_element_paragraph_article)
    content_paragraph = content[start_index:].strip()
    paragraph_start = content_paragraph.find('<font>')

    while paragraph_start != -1:
        paragraph_end = content_paragraph.find('<font>', paragraph_start)

        if paragraph_end != -1:
            paragraph = content_paragraph[paragraph_start + len('<p>'):paragraph_end].strip()
            paragraphs.append(paragraph)
            paragraph_start = paragraph_end + len('</font>')
        else:
            print("Closing </font> tag not found")
            break
else:
    print("Font element was not found")

return paragraphs

If anything, let me know if you have questions. I’m happy to answer them back 🙂

2

Answers


  1. Chosen as BEST ANSWER

    As @Sepu Ling pointed out, it did the trick. The final result is pretty good. This is what I did without enumerating each:

    def paragraphs(url):
    '''Return the paragraph list of the specified URL'''
    
    content = html_content(url)
    paragraphs = []
    start_tag = '<div class="item-article-body size-20">'
    end_tag = '</div>n</div>n</div>'
    start_index = content.find(start_tag)
    end_index = content.find(end_tag, start_index)
    
    if start_index != -1 and end_index != -1:
        extracted_text = content[start_index + len(start_tag):end_index]
        temp = extracted_text.split('<br>')
        for data in temp:
            paragraph = remove_html_tags(data).strip()
            if paragraph:
                paragraphs.append(paragraph)
        return paragraphs
    else:
        print("Article not found ")
        return []
    
    def remove_html_tags(text):
        clean = re.compile('<.*?>')
        return re.sub(clean, '', text)
    

    I removed the extra br tag because I want to preserve the paragraphs. If I want every single paragraph as one, I would add that extra br tag in it.


  2. It sounds like you can’t crawl paragraphs of an article with your code

    If I understand wrong, please tell me

    def remove_html_tags(text):
        clean = re.compile('<.*?>')
        return re.sub(clean, '', text)
    
    paragraphs = []
    start_tag = '<div class="item-article-body size-20">'
    end_tag = '</div>n</div>n</div>'
    start_index = content.find(start_tag)
    end_index = content.find(end_tag, start_index)
    
    if start_index != -1 and end_index != -1:
        extracted_text = content[start_index + len(start_tag):end_index]
        temp = extracted_text.split('<br><br>')
        for i,data in enumerate(temp):
            temp[i] = remove_html_tags(data).strip()
            if not temp[i]:
                temp.remove(temp[i])
        print(temp)
    else:
        print("article not found ")
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search