<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ida Delphine</title>
    <description>The latest articles on DEV Community by Ida Delphine (@idadelveloper).</description>
    <link>https://dev.to/idadelveloper</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F526619%2F13b7fd36-fbab-4800-b2a3-60a97fa40d12.jpeg</url>
      <title>DEV Community: Ida Delphine</title>
      <link>https://dev.to/idadelveloper</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/idadelveloper"/>
    <language>en</language>
    <item>
      <title>Building Thriving Communities from Scratch: A Step-by-Step Guide</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 21 Apr 2024 22:55:46 +0000</pubDate>
      <link>https://dev.to/idadelveloper/building-thriving-communities-from-scratch-a-step-by-step-guide-2bk0</link>
      <guid>https://dev.to/idadelveloper/building-thriving-communities-from-scratch-a-step-by-step-guide-2bk0</guid>
      <description>&lt;p&gt;In today's increasingly connected world, communities are more than just groups of people with shared interests; they're vibrant ecosystems that foster connection, collaboration, and growth. But building a community from scratch, one that thrives and endures, requires more than just throwing people together. It's a strategic endeavor that demands patience, dedication, and a well-defined roadmap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Foundation: Purpose and People
&lt;/h2&gt;

&lt;p&gt;Every thriving community is built on a solid foundation of purpose. This purpose serves as the North Star, guiding the community's direction and motivating its members. It could be a shared passion for woodworking, a desire to support aspiring entrepreneurs, or a commitment to environmental sustainability. Clearly define your purpose early on, and ensure it resonates with your target audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Team: Diverse Skills, Shared Vision
&lt;/h2&gt;

&lt;p&gt;Assembling a strong organizing team is crucial. Look for individuals with complementary skillsets, from event planning and social media management to content creation and design. But beyond technical expertise, prioritize those who share your community's vision and are passionate about fostering its growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Establishing the Hub: Where Your Community Connects
&lt;/h2&gt;

&lt;p&gt;Choosing the right communication platform is essential. Consider the demographics of your target audience. Will a platform like Discord resonate more with a gaming community, or would a professional network like LinkedIn be a better fit for a business-oriented group? Whichever platform you choose, ensure consistency – use the same username across all social media channels to make it easy for people to find you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Growing Your Community: Strategic Outreach
&lt;/h2&gt;

&lt;p&gt;Targeted outreach is key to attracting the right members. If you're building a community for aspiring writers, connect with creative writing programs at universities. For a community focused on fitness, partner with local gyms or health clubs. Explore various outreach methods – social media campaigns, guest lectures at relevant events, or even community radio announcements – and track which tactics yield the best results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nurturing the Ecosystem: Engagement is Key
&lt;/h2&gt;

&lt;p&gt;Once members join, make them feel welcome. Clearly outline community guidelines and encourage them to invite others who might share your vision. But building a community goes beyond mere numbers. Active engagement is the lifeblood of any thriving community. Here's where your content strategy comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content is King: Providing Value to Your Members
&lt;/h2&gt;

&lt;p&gt;Develop a content calendar that aligns with your community's purpose. This could include insightful blog posts, informative webinars, or interactive workshops. Encourage member participation through discussions, Q&amp;amp;A sessions, and collaborative projects. Remember, the goal is to provide value and keep members engaged in a meaningful way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Momentum: A Culture of Collaboration
&lt;/h2&gt;

&lt;p&gt;Plan events that resonate with your members' interests. Host meetups, online workshops, or even hackathons that address challenges relevant to your community's purpose. Remember, it's not just about you – empower your members to take ownership. Foster a culture of collaboration where members can share their expertise, mentor each other, and contribute to the community's growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sustainability: Tracking, Analysis, and Adaptation
&lt;/h2&gt;

&lt;p&gt;Track your progress using the KPIs you established with your team. Analyze these metrics regularly to identify what's working and where you can improve. Be prepared to adapt your strategy based on your findings.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power of Partnership: Collaboration for Impact
&lt;/h2&gt;

&lt;p&gt;Building strong relationships with other communities in your niche can be mutually beneficial. Explore opportunities for collaboration, such as co-hosting events or cross-promotion. This not only expands your reach but also fosters a sense of connection within the broader ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Legacy: Succession Planning
&lt;/h2&gt;

&lt;p&gt;To ensure the long-term sustainability of your community, consider developing a succession plan. Identify and cultivate passionate members who can step up and take on leadership roles when needed. This ensures your community continues to thrive, even as its core team evolves.&lt;/p&gt;

&lt;p&gt;Building a thriving community is a journey, not a destination. By following these steps, fostering a welcoming and engaging environment, and constantly adapting to your members' needs, you can cultivate a space where connection, collaboration, and shared purpose flourish.&lt;/p&gt;

</description>
      <category>community</category>
    </item>
    <item>
      <title>Generative AI &amp; Gemini</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 14 Apr 2024 20:15:18 +0000</pubDate>
      <link>https://dev.to/idadelveloper/generative-ai-gemini-40d6</link>
      <guid>https://dev.to/idadelveloper/generative-ai-gemini-40d6</guid>
      <description>&lt;h2&gt;
  
  
  What is Generative AI?
&lt;/h2&gt;

&lt;p&gt;Generative AI has become very popular lately where its being used by the masses to generate different types of content ranging from text, images, videos, etc. Generative AI is a subset of artificial intelligence (AI) techniques that focus on generating new, original content based on input data or patterns learned from existing data. Unlike traditional AI models that are designed for specific tasks such as classification or prediction, generative AI models are capable of creating entirely new data samples that resemble the training data they were exposed to. It makes the uses of generative models which generate new content based on a learned probability distribution of existing data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Gemini?
&lt;/h2&gt;

&lt;p&gt;Gemini is a LLM (large language model) developed by Google Deepmind capable of generating text, translating language and writing all sorts of creative content. It is &lt;strong&gt;multimodal&lt;/strong&gt; in the sense that it can understand a wide range of information ranging from text,audio, images, etc and provide output accordingly.&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="https://gemini.google.com/app"&gt;here&lt;/a&gt; to try out it's capabilities.&lt;/p&gt;

&lt;p&gt;I know this article is short. In the next we will be building a generative AI application with the &lt;a href="https://github.com/google-gemini/cookbook"&gt;Gemini API&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>google</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>React's virtual DOM explained</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 07 Apr 2024 21:16:37 +0000</pubDate>
      <link>https://dev.to/idadelveloper/reacts-virtual-dom-explained-2i07</link>
      <guid>https://dev.to/idadelveloper/reacts-virtual-dom-explained-2i07</guid>
      <description>&lt;p&gt;React is an opensource JavaScript library which is used to build web interfaces using components. What makes React really cool is the fact that it can be used to make re-usable components. In addition, it is very flexible and has a huge community.&lt;/p&gt;

&lt;p&gt;As a web developer, the DOM (Document Object Model) should not be a new concept. But to refresh your memory, the DOM basically represents a web page in a hierarchical tree-like structure. This web page is also known as a document and it is kinda an object-oriented representation of the web page. You really get to appreciate the DOM when you try to incorporate certain functionalities into your web page or manipulate it with JavaScript. Through the DOM, you can target specific HTML elements and modify them accordingly. The DOM was built using an API which makes it language agnostic. This means you must not necessarily use JavaScript to manipulate it.&lt;/p&gt;

&lt;p&gt;Every React developer should understand what the virtual DOM entails. Usually, rendering a web page is fast. But when the DOM is manipulated where a specific item changes, the entire webpage is re-rendered which kind of slows everything down. This is where the virtual DOM comes in. The virtual DOM is a lighter abstraction of the DOM which is saved somewhere in the browser's memory. The virtual DOM does not replace the real DOM. It aids in making the rendering of web pages more efficient. The state you want the UI to be is first specified and when changes are made to the virtual DOM, it compares it with the changes just before it was updated. Once the element that was changed is identified, only that element is targeted and updated on the real DOM. Without the virtual DOM, the entire page could be re-rendered because of a tiny update.&lt;/p&gt;

&lt;p&gt;Learn more &lt;a href="https://blog.logrocket.com/virtual-dom-react/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>learning</category>
    </item>
    <item>
      <title>Getting the Outreachy Internship</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 31 Mar 2024 21:41:48 +0000</pubDate>
      <link>https://dev.to/idadelveloper/getting-the-outreachy-internship-2mda</link>
      <guid>https://dev.to/idadelveloper/getting-the-outreachy-internship-2mda</guid>
      <description>&lt;p&gt;If you are new to opensource, one of the best and rewarding ways to get your foot in the door or start out is to participate in programs like &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt;. Especially for students who are looking to build experience and work on real life projects. When you hear "outreachy", think of 3 things; &lt;strong&gt;remote&lt;/strong&gt;, &lt;strong&gt;paid&lt;/strong&gt; and &lt;strong&gt;open source/open science&lt;/strong&gt;. To sum it up, Outreachy is a remote paid internship program aimed at increasing/promoting diversity and inclusion in open source and open science. This internship happens twice a year with one cohort starting in May and the other in December.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Outreachy works
&lt;/h2&gt;

&lt;p&gt;Outreachy is particularly meant for individuals who belong to underrepresented groups in the field of technology so women are highly encouraged to apply. Interns will have the opportunity to contribute to different opensource projects in different areas like programming, research, user experience, documentation, graphical design, data science, marketing, user advocacy, event planning,etc. So there is definitely something for everyone and this is just to make you understand "open source" is not only limited to code contributions.&lt;/p&gt;

&lt;p&gt;For every Outreachy cohort, there are a couple of mentoring opensource organizations with each having specific and detailed projects which the potential intern will work on. The number of project per organization determines the number of interns. For example, it is most likely that if a single mentoring organization has 3 projects, nothing less than 3 interns will be needed for that specific organization. Bare in mind that the various projects may vary in terms or requirements and skill needed. However, they are all designed to be completed within a span of approximately 3 months with 7000 USD to be paid. The intern will work along side their mentors who are experienced contributors in that organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Procedure
&lt;/h2&gt;

&lt;p&gt;There are 3 major steps to be taken to be considered for the outreachy internship. We have the &lt;strong&gt;initial application&lt;/strong&gt;, &lt;strong&gt;contribution phase&lt;/strong&gt;, and &lt;strong&gt;final application&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initial Application&lt;/strong&gt;: This is the first step of the application process and it is often taken for granted by many. Here, the outreachy organizers want to know more about your background and understand how both underrepresented and discriminated on you have been and a minority or underrepresented group. You are to write a couple of essays and submit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contribution Period&lt;/strong&gt;: This is the next stage after the initial applications. Once you submit your initial application, the outreachy organisers will review your essays and if they are convincing such that they show you are underrepresented, can commit to 40hrs/week of the internship and passionate, you will be accepted into the contribution phase. I will say this step is the most difficult as you are supposed to find projects that interest you and make as many contributions as you wish to the organisation the project is under. This is the stage where you get to know more about the organization and start exploring it's codebase (if it's programming you are going for). This is also where you get to bond with the community and your potential mentor. You have the choice of picking up to 3 projects you are interested in working on. But know that you will have to make contributions to all the organizations they are under and if you are to be selected as an intern you will only be selected for one. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Final Application&lt;/strong&gt;: This is the final step of the application process. After you have made contributions, you will have to submit a final application where you will log the contributions you made, provide a road map of how you plan on working on your selected project(s) and provide extra information about you.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips and Tricks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read the entire applicant guide on the outreachy website.&lt;/li&gt;
&lt;li&gt;Take your time to answer the questions in your initial application. If you can include some examples of past experiences where necessary that highlight the bias/discrimination you have faced that could help. Also make sure everything about your application proves you will be able to commit 40hrs a week if granted the internship with little or no interruptions from school, work, etc. Finally, try to submit your application latest 1 week before the deadline.&lt;/li&gt;
&lt;li&gt;You can also start checking out mentoring organizations before the contribution period. There is a "current projects" page you can checkout which will be updated as days go by with more organizations and projects. On this page you will get to see listed organizations and associated projects. You will see tiny details about the technologies required and skill level. You can use this to your advantage. If you see a project that interests you and your skills match, you can start doing your research and learning about it right before the contribution period. That way when the contribution period officially starts, you should have grasped the basic and gone through their code base. &lt;/li&gt;
&lt;li&gt;Make sure you go for a project where most of your skills match.&lt;/li&gt;
&lt;li&gt;Focus on contributing to just a single organization and take your time to submit quality over quantity. &lt;/li&gt;
&lt;li&gt;Make sure you've joined the community's most active public chat.&lt;/li&gt;
&lt;li&gt;Be active within the community and attend all their calls, contribute to their discussions.&lt;/li&gt;
&lt;li&gt;Reach out your mentor if you face any difficulty but make sure you have done your research. Work alongside your mentor to come up with the breakdown of your project plan for your final application.&lt;/li&gt;
&lt;li&gt;Even after the final application, stick around and still show interest in the community and its activities.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Understanding license compliance in open source projects</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 24 Mar 2024 20:13:45 +0000</pubDate>
      <link>https://dev.to/idadelveloper/understanding-license-compliance-in-open-source-projects-4dmb</link>
      <guid>https://dev.to/idadelveloper/understanding-license-compliance-in-open-source-projects-4dmb</guid>
      <description>&lt;p&gt;As an open source contributor, aspiring contributor or maintainer, it is very important to take licences very seriously as they determine how you can interact with any open source project. Open source licences are basically legal agreements which define how open source software should be read, ran, revised and redistributed. For a start, lets talk about the types of opensource licences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissive vs Copyleft licenses
&lt;/h2&gt;

&lt;p&gt;Free and opensource licences can be divided into two main categories - &lt;strong&gt;permissive&lt;/strong&gt; and &lt;strong&gt;copyleft&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Permissive licenses:&lt;/strong&gt; Permissive licenses allow any one to use, modify and redistribute software without any restrictions. It basically means derivatives of such software under this license could be made propriety or closed-source irrespective of the fact that their parent project is opensource. Some examples of such licenses are the MIT, Apache licences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copyleft licenses:&lt;/strong&gt; Copyleft licenses allow you to use,modify and redistribute software however, the software has the changes are shared other same license. This measns the software and its derivatives must remain free and open for everyone to use. Some examples include the GNU GPL licences.You can see that copyleft licenses protect the freedom of downstream users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now realize that before starting an open source project or interact with one, it is important to check what license it is under. &lt;/p&gt;

&lt;h2&gt;
  
  
  Open source license compliance
&lt;/h2&gt;

&lt;p&gt;They say open source software is free but is it really? Are all open source software really free? The "free" part only means you have the freedom to use, modify, and redistribute it. However, the license really determines how you actually utilize these freedoms. This is why we have to understand open source license compliance. You might be wondering what the point might be since there's no active company enforcing it. &lt;/p&gt;

&lt;p&gt;First of all, you really want to take license compliance seriously because you wouldn't want to have to deal with any lawsuits or penalties. Remember these licenses are legal contracts which give authorization and permission on how opensource software should be used, modified and distributed. Breaching the terms of this contract could come with some consequences which are not worth it. Compliance goes a very long way to mitigate any legal risks that could pose a threat to organizations. In addition, these licenses protect the intellectual property rights of both the original authors and subsequent contributors and compliance comes in to enforce the intentions of how the original authors intend for their software to be used.It ensures downstream projects abide by the rules of the original authors enforcing their rights. Further more, compliance helps build trust and transparency within a community as everyone is on the same page as per how the software is supposed to be used, modified or distributed. Failure to comply to the licenses might actually break the trust, lead to disputes, and possibly affect the community behind the software negatively.&lt;/p&gt;

&lt;p&gt;To conclude, open source license compliance is essential for ensuring legal, ethical, and practical adherence to the terms of open source licenses. It helps protect intellectual property rights, preserve community trust, mitigate legal risks, and promote the principles of openness and collaboration in software development.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Finding an open source project and contributing to it</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 17 Mar 2024 17:24:16 +0000</pubDate>
      <link>https://dev.to/idadelveloper/finding-an-open-source-project-and-contributing-to-it-5gak</link>
      <guid>https://dev.to/idadelveloper/finding-an-open-source-project-and-contributing-to-it-5gak</guid>
      <description>&lt;p&gt;Finding an open source project is one thing and contributing to it is another. What makes a project or anything opensource is the fact that anyone is free to view it, run it, and most importantly revise and share it.Everyone has their reason to getting involved or contributing to open source and there is honestly no wrong reason because any meaningful contribution in whatsoever way goes a long way. If you're in doubt about contributing to open source, below are some great reasons you should consider it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of getting involved in opensource
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Improve your technical skills&lt;/li&gt;
&lt;li&gt;Gain more work experience&lt;/li&gt;
&lt;li&gt;Broaden your horizons&lt;/li&gt;
&lt;li&gt;More credibility as you can prove your skills&lt;/li&gt;
&lt;li&gt;Network with people from different backgrounds&lt;/li&gt;
&lt;li&gt;Turn your ideas into life&lt;/li&gt;
&lt;li&gt;Build your portfolio&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finding an opensource project
&lt;/h2&gt;

&lt;p&gt;If you do not have any opensource project in mind and are genuinely interested in contributing to open source, I have a tip to share. You can start by thinking about what you love doing. Could be coding, design, writing. Then you look around you; what are those tools or technologies you enjoy using or frequent day to day? Could be Firefox, Wikipedia, Git, VS Code, etc. Find out if they are open source and have a public repository. Another way to find open source projects is to participate in programs like &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt;, &lt;a href="https://www.outreachy.org/"&gt;Outreachy&lt;/a&gt;, &lt;a href="https://summerofcode.withgoogle.com/"&gt;Google Summer of Code&lt;/a&gt;, etc. Even if you are not actively participating, you could visit their pages and check out past projects and organizations that were involved and get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing to an open source project (code contibution)
&lt;/h2&gt;

&lt;p&gt;Now you've found that project but you might be overwhelmed on how to get started with contributing to it. Here are some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visit the project's website and learn all it's about. Also find information about joining their community or public chat and make sure you join. &lt;/li&gt;
&lt;li&gt;Go through the README file available in the root directory of the project's Git repository.&lt;/li&gt;
&lt;li&gt;Download the latest release of the project and experience it first hand. Know the basic functionalities and how to navigate across the application.&lt;/li&gt;
&lt;li&gt;Set Up your development environment by following the instructions on the README.md file and also read the CONTRIBUTING.md file for relevant info about contributing to the repo.&lt;/li&gt;
&lt;li&gt;Clone the project and familiarize yourself with the code base and its documentation. The aim for this would be to help you build and run the project locally. &lt;/li&gt;
&lt;li&gt;The issues are a great place to start once already familiar with the project and its code base. For newcomers, find issues labeled “newcomer” and “good first issue”.&lt;/li&gt;
&lt;li&gt;Once you are familiar with working on issues or some of your PR have been successfully merged into the codebase, you can continue working on more issues with other tags like “help wanted”, “bug”, “feature”, etc. &lt;/li&gt;
&lt;li&gt;If you are interested in working on an issue, comment on it and indicate your interest in working on it. You will be provided with more details and any resources requested and assigned if no other individual is assigned to it.&lt;/li&gt;
&lt;li&gt;Fork the repository (if Github or Gitlab)&lt;/li&gt;
&lt;li&gt;Create a branch with a name that matches the issue (or check the project's contributing guidelines on naming branches)&lt;/li&gt;
&lt;li&gt;Make your changes and be sure it adheres to the coding standards/style.&lt;/li&gt;
&lt;li&gt;Write a meaningful commit message which mentions the changes that have been introduced. Do not make several different unrelated changes and bundle them in a single commit. &lt;/li&gt;
&lt;li&gt;Push changes to your remote fork.&lt;/li&gt;
&lt;li&gt;Submit pull requests to the specified branch as per the contribution guidelines.&lt;/li&gt;
&lt;li&gt;Make sure your pull requests are descriptive and tag the issue you are resolving to align issues with incoming fixes/changes. All PRs should match specific issues.
PRs should be opened to match specific issues by tagging them. This is an important step to help align the issues with incoming fixes and changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you've submitted a PR, you wait for the review and depending on your changes, you might receive comments from the reviewer, they might request more changes or approve the PR. Address them accordingly and be able to accept a little constructive criticism. In addition, be polite in your communications and inquiries. Also make sure your questions are elaborate and you've done your research.&lt;/p&gt;

&lt;p&gt;Making that first contribution might not be easy but as you get acquainted with the code base, it become a piece of cake and with time you will find yourself helping out new contributors find their way around. I believe it's important to contribute to project you enjoy using or those whose values and cause resonate with you so that you don't easily lose your motivation prompting you to stick around longer.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Sending out SMS messages via Twilio</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 10 Mar 2024 22:12:07 +0000</pubDate>
      <link>https://dev.to/idadelveloper/sending-out-sms-messages-via-twilio-47fh</link>
      <guid>https://dev.to/idadelveloper/sending-out-sms-messages-via-twilio-47fh</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/idadelveloper/web-scrapping-in-python-part-2-j0m"&gt;previous post&lt;/a&gt;, we scrapped a job posting site and were able to get a couple of jobs. Rememeber, I mentioned in &lt;a href="https://dev.to/idadelveloper/web-scraping-with-python-part-1-43jb"&gt;Part 1&lt;/a&gt; we will scrap a webpage and sent jobs to a user via SMS. Talking about SMS you should definitely checkout this &lt;a href="https://dev.to/idadelveloper/how-sms-messages-are-handled-between-2g-3g-4g-5g-2kk9"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before we jump right into creating the SMS functionality, let's first of all store our scrapped data into a very simple SQLite database. I will be creating a new file called &lt;code&gt;data.py&lt;/code&gt;. This is where the code handling our data storage will reside. &lt;br&gt;
We will create a class which will handle all operations in relation to the data base from creating to adding to deleting data. For now we will implement a few methods to be sure the basic functionality at least works. When the class will be instantiated, a SQLite connection will be established and both the database and the table will be created if they don't exist. We will have 2 methods to save the data to the database and also retrieve data (for now). When storing our data, we will make sure the URL is the primary key to make sure duplicate data won't be saved. With time we will implement error handling and refine the class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JobsDataBase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs_data.sqlite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CREATE TABLE IF NOT EXISTS jobs (id VARCHAR, description VARCHAR, PRIMARY KEY (id))&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;INSERT OR IGNORE INTO jobs (id, description) values (&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;done&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getjobs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs_data.sqlite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM jobs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's create a function called &lt;code&gt;save_data&lt;/code&gt; within &lt;code&gt;scrapper.py&lt;/code&gt;. Don't forget to import &lt;code&gt;data.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def save_data(jobs):
    jobs_data = data.JobsDataBase()
    for j in jobs:
        jobs_data.save(j[0], j[1])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;get_job_details&lt;/code&gt; function in &lt;code&gt;scrapper.py&lt;/code&gt; has been modified to return a list of lists containing job URLs and descriptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_job_details&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;job_details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;job-description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;job_details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;job_details&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's dive into implementing our SMS functionality. After savind data into our database, we want to send out an SMS to the user. Considering the fact that there won't be duplicte data stored in the database, there are zero chances of sending out an SMS more than once (unless there's a bug in the code)&lt;/p&gt;

&lt;p&gt;We will be using Twilio to implement the SMS functionality. wilio is a cloud-based communications company that offers tools for making and receiving calls, sending messages, and more. Twilio's products include voice, video, messaging, authentication, and more.&lt;/p&gt;

&lt;p&gt;Before we dive into the code, we will start by creating a &lt;a href="https://www.twilio.com/try-twilio"&gt;Twilio&lt;/a&gt; account and download its python [helper library].(&lt;a href="https://github.com/twilio/twilio-python"&gt;https://github.com/twilio/twilio-python&lt;/a&gt;). Run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip3 install twilio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you setup your Twilio console and get your &lt;code&gt;account SID&lt;/code&gt; and &lt;code&gt;Auth token&lt;/code&gt;. Create the variables &lt;code&gt;account_sid&lt;/code&gt; and &lt;code&gt;auth_token&lt;/code&gt; in your code and assign them their values. Be sure to also generate your Twilio phonenumber which you will use to send SMS messages.&lt;/p&gt;

&lt;p&gt;Now lets start by importing our Twilio client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twilio.rest&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will create a &lt;code&gt;send_sms&lt;/code&gt; function. In the fuction you can see we when conposing the message to be sent we limited the characters. That's because there's a character limit and for now we won't dwell on hacking that limitation as our main focus is sending out an SMS via Twilio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account_sid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Visit site: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;from_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;twilio-phone-number&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;receiver-phone-number&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will be sending out an SMS after saving any job into the database. So we will add an extra line in our &lt;code&gt;save_data&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;jobs_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;JobsDataBase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;jobs_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="nf"&gt;send_sms&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the &lt;code&gt;save_data&lt;/code&gt; function will send out SMS messages depending on the number of jobs. In our next articles, we will refine the data base, send out SMS messages with all the details, etc&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>python</category>
      <category>sms</category>
      <category>twilio</category>
    </item>
    <item>
      <title>Web Scraping With Python (Part 2)</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 03 Mar 2024 21:45:32 +0000</pubDate>
      <link>https://dev.to/idadelveloper/web-scrapping-in-python-part-2-j0m</link>
      <guid>https://dev.to/idadelveloper/web-scrapping-in-python-part-2-j0m</guid>
      <description>&lt;p&gt;We shall be continuing where we left our &lt;a href="https://dev.to/idadelveloper/web-scraping-with-python-part-1-43jb"&gt;Python scrapper&lt;/a&gt;. Our program was able to return all the job links of the homepage of &lt;a href="https://www.fossjobs.net/"&gt;fossjobs.net&lt;/a&gt;. However, we shouldn't end there. How about we build a tool that sends the user SMS messages of jobs they match with? That will mean we will have to access those individual links, access their info and make sure they match the user. For now we will be extracting info from the job link like the summary, job description, eligibility/qualifications/skills required and the link or steps to apply. This might be a little tricky but firstly we will start slowly.&lt;/p&gt;

&lt;p&gt;Each of those job links have different formats of how their data is organized. You can clearly see that format of this &lt;a href="https://www.fossjobs.net/job/11363/internet-freedom-nonprofit-seeks-rust-developer-at-tor-project/"&gt;rust developer role&lt;/a&gt; is different from this &lt;a href="https://www.fossjobs.net/job/11358/software-engineer-trust-and-safety-product-at-wikimedia-foundation/"&gt;software engineer role&lt;/a&gt;. Considering the fact that there is no consistent format across all links, we will basically just pull everything from the links and pass the out put to a generative AI model to extract the relevant data we need. &lt;/p&gt;

&lt;p&gt;This is how we previously left our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.fossjobs.net/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Gets html content of fossjobs.net
&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# extracts all html elements with an 'a' tag and 'neutral-link' class
&lt;/span&gt;&lt;span class="n"&gt;job_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;neutral-link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job_element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;job_elements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;job_link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job_element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;href&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job_link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's high time we "modularize" our code by placing different functionalities in different functions. The first function will accept a URL and return a list of links meanwhile the second function will accept this list of job urls, iterate through them and grab all the job details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_job_urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Gets html content of fossjobs.net
&lt;/span&gt;    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# extracts all html elements with an 'a' tag and 'neutral-link' class
&lt;/span&gt;    &lt;span class="n"&gt;job_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;job_links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job_element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;job_elements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;job_link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job_element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;href&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;job_links&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job_link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;job_links&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's code the second function. We will call it &lt;code&gt;get_job_details&lt;/code&gt; and it will accept a list of strings and print out the job details for now. Based on the html content there is a &lt;code&gt;div&lt;/code&gt; with a  class called &lt;code&gt;job-description&lt;/code&gt; where in this div we have a paragraph tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_job_details&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;job_details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;div&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;job-description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;job_details&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;p&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;job_details&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next thing we will do is get to organize the data in a format which will enable us send jobs that are a good fit for our users and also to exclude sending jobs which are past the deadline.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Web Scraping With Python (Part 1)</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 25 Feb 2024 21:04:08 +0000</pubDate>
      <link>https://dev.to/idadelveloper/web-scraping-with-python-part-1-43jb</link>
      <guid>https://dev.to/idadelveloper/web-scraping-with-python-part-1-43jb</guid>
      <description>&lt;p&gt;Web Scraping is the act of extracting data from the web. In this tutorial, we will build a web scrapper that will extract information about various jobs. There are several python web scrapping libraries like requests, beautiful soup, etc&lt;/p&gt;

&lt;p&gt;Let's start by creating our project directory in which we will have our virtual environment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now activate your virtual environment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt; venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that your virtual environment is activated, you can conveniently install your library.&lt;/p&gt;

&lt;p&gt;Now create your working directory and enter it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir python-scrappper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd python-scrapper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your requirements.txt file to keep track of all libraries/dependencies downloaded&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the requests library&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m pip install requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a file &lt;code&gt;scrapper.py&lt;/code&gt; to carryout the scrapping from the &lt;a href="https://www.fossjobs.net/"&gt;fossjobs.net&lt;/a&gt; job board.&lt;br&gt;
We will start by writing a simple program using to the request library to get all the html from the fossjobs website and write to a text file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.fossjobs.net/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;readme.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parsing with beautiful soup
&lt;/h2&gt;

&lt;p&gt;Now that we have scrapped data from the fossjobs.net site, the output looks like a huge mess with just HTML tags all over the place. We are going to use beautiful soup to parse the data in the HTML. First, let's install beautiful soup&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m pip install beautifulsoup4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will add 2 extra lines in our code. The first one importing beautiful soup and the other one which creates a &lt;code&gt;BeautifulSoup&lt;/code&gt; object that with our html content as its input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.fossjobs.net/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;readme.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second argument of the &lt;code&gt;BeautifulSoup&lt;/code&gt; object describes the type of parser which in this case will be an html parser.&lt;/p&gt;

&lt;p&gt;When you visit a job board there are some key things you are looking for. The job title, it's description, and link to apply. These are what we want to currently extract from our html content. We can extract information by certain html elements like classes or ids. In our HTML content, we can see for every job post, there is an &lt;code&gt;article&lt;/code&gt; tag with a class name &lt;code&gt;post&lt;/code&gt;. In this scenario, we want to keep it simple by extracting just the links to all the job application pages. So we will make use of the &lt;code&gt;a&lt;/code&gt; tag and the &lt;code&gt;neutral-link&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.fossjobs.net/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Gets html content of fossjobs.net
&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# extracts all html elements with an 'a' tag and 'neutral-link' class
&lt;/span&gt;&lt;span class="n"&gt;job_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;class_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;neutral-link&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;job_element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;job_elements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;job_link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;job_element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;href&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;job_link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our output should look somewhat like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://tryquiet.org/jobs/

https://grnh.se/230c253d1us

https://apply.workable.com/digidem/j/96343A29BE/

https://okfn.org/en/jobs/senior-developer/

https://www.fsf.org/news/fsf-job-opportunity-outreach-and-communications-coordinator

https://wikimedia-deutschland.softgarden.io/job/40776229?l=de

https://wikimedia-deutschland.softgarden.io/job/40775956?l=de
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add all dependencies in the requirements.txt file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have successfully scrapped the fossjobs.net website and gotten the links of all jobs in the home page. Next thing we will do is parse the content of these links and get other useful details.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How SMS messages are handled between 2G, 3G, 4G &amp; 5G</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 18 Feb 2024 20:52:14 +0000</pubDate>
      <link>https://dev.to/idadelveloper/how-sms-messages-are-handled-between-2g-3g-4g-5g-2kk9</link>
      <guid>https://dev.to/idadelveloper/how-sms-messages-are-handled-between-2g-3g-4g-5g-2kk9</guid>
      <description>&lt;p&gt;Before the internet became a thing and mobile apps like WhatsApp, Signal, etc emerged for text communication on mobile devices, there was SMS. SMS stands for &lt;strong&gt;Short Messaging Service&lt;/strong&gt; and that's pretty self explanatory as messages are limited to 160 characters in length. &lt;/p&gt;

&lt;p&gt;With that said, you have probably sent out an SMS message before and even if you have never sent one, you've definitely received one. Have you ever wondered how it's possible to send SMS messages across different networks to different devices? That's thanks to the &lt;strong&gt;GSM (Global System for Mobile Communications)&lt;/strong&gt; standards which ensure compatibility and interoperability between mobile devices and networks.&lt;/p&gt;

&lt;h2&gt;
  
  
  A little about cellular networks
&lt;/h2&gt;

&lt;p&gt;Cellular networks allow mobile devices such as smartphones, tablets, and other wireless-enabled devices to communicate with each other and access the internet. They are made up of several components that work hand in glove. These include the &lt;em&gt;mobile switching center (MSC), central office (CO), cell, base station, antenna&lt;/em&gt;, etc. As time passes by, cellular networks have evolved with improvements communication capabilities, data speeds, and the range of services offered to users. This evolution happened in "generations" reason for the "G" you see in 2G, 3G, etc&lt;/p&gt;

&lt;h2&gt;
  
  
  2G, 3G, 4G &amp;amp; 5G
&lt;/h2&gt;

&lt;p&gt;Before we dive into the these generations, it is worth talking about &lt;strong&gt;1G&lt;/strong&gt; - the first generation which laid the foundation for mobile communication. It made use of analog signals for voice communication and it had several limitations which includes limited capacity to support a high volume of users, no encryption, and low call quality. The other generations came in to improve the quality of service of previous generations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;2G ( Early 1990s to early 2000s)&lt;/strong&gt;: The second generation significantly advanced the shortcomings of is predecessor and played a crucial role in the advancement of mobile communication. It played a huge role in improving voice quality and this was where GSM became dominant as it was &lt;strong&gt;time-division multiple access (TDMA)-based&lt;/strong&gt;. IN TDMA, all the signals are given timeslots to pass through a single channel. What made 2G really special was phone conversations became encrypted, more users per frequency band, the introduction of SMS messages and the &lt;strong&gt;SIM (Subscriber Identity Module)&lt;/strong&gt; card. International roaming was also introduced where users could use their mobile devices in other countries with 2G network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;3G (Early 2000s to around 2010)&lt;/strong&gt;: The third generation came about with higher data transfer rates, introduction of mobile internet access, video calling, and multimedia services.It made use of Wideband Code Division Multiple Access (WCDMA), CDMA2000, and others&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;4G/4.5G(LTE Advanced and LTE Advanced Pro) (Around 2010 onwards)&lt;/strong&gt;: The generation brought about significant increase in data speeds, lower latency, and improved capacity. 4G enabled widespread mobile broadband access, supporting applications like video streaming and online gaming. The primary standard was &lt;strong&gt;Long-Term Evolution (LTE)&lt;/strong&gt; which is a wireless broadband standard for mobile communication and data transfer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;5G (2019 onwards)&lt;/strong&gt;: The fifth generation came in with extremely high data speeds, low latency, and support for a massive number of connected devices. It was designed to meet the diverse requirements of applications like augmented reality, virtual reality, IoT, and autonomous vehicles. Its primary standard is &lt;strong&gt;5G NR&lt;/strong&gt; (New Radio) which is designed to provide faster and more responsive mobile experiences than previous 4G standards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Handling of SMS in 2G, 3G, 4G &amp;amp; 5G
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. 2G&lt;/strong&gt;&lt;br&gt;
The user starts by composing a message on their mobile device which is then forwarded to the &lt;strong&gt;Short Message Service Center (SMSC)&lt;/strong&gt; - a centralized server that is responsible for storing, forwarding, and delivering SMS messages. It receives the incoming message and checks the address of its recipient to know where the message will be delivered to. The SMSC then checks if the recipient's device is available. If it is reachable, the SMSC forwards the message to their &lt;strong&gt;home location register (HLR)&lt;/strong&gt;, which is a database that contains subscriber information. If the recipient isn't available, the SMSC stores the message until the recipient become available (e.g turning on device). After the message has been routed to the receiver, the SMSC requests for a an acknowledgement to prove the message has indeed been delivered. If you notice when you send out an SMS you will find a single tick by the message blob which signifies its been sent. When the SMSC receives the acknowledgement of successful delivery it then notifies the user's device reason you realize the single tick changes to double ticks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. 3G&lt;/strong&gt;&lt;br&gt;
With 3G, it follows the same steps as 2G. What makes 3G better is the rate of data transfer is faster and there is the ability for users to send pictures, videos, audios through &lt;strong&gt;Multimedia Messaging Service (MMS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. 4G&lt;/strong&gt;&lt;br&gt;
4G follows same steps as 2 &amp;amp; 3G. What makes it better than its predecessors is all the capabilities of the previous generations are further enhanced and more efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. 5G&lt;/strong&gt;&lt;br&gt;
With 5G, once the message is composed and sent, it goes to the &lt;strong&gt;5G core (5GC) network&lt;/strong&gt;. Within the 5GC, ther is the &lt;strong&gt;Session Management Function (SMF)&lt;/strong&gt; which is responsible for handling the signaling and routing of messages. It also contains the &lt;strong&gt;Access and Mobility Management Function (AMF)&lt;/strong&gt; which is for handling SMS when devices move across different areas within the 5G network. Furthermore, there is the  &lt;strong&gt;User Plane Function (UPF)&lt;/strong&gt; which ensures the efficient and reliable transport of SMS data between the sender and recipient. The 5G network processes and delivers the message similar to that of previous generations but with significantly higher data rates.&lt;br&gt;
5G networks are designed to provide low-latency communication. This can enhance the real-time delivery of SMS messages, making the service more responsive.&lt;/p&gt;

</description>
      <category>sms</category>
    </item>
    <item>
      <title>Managing Deadlock In Databases</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 11 Feb 2024 15:58:31 +0000</pubDate>
      <link>https://dev.to/idadelveloper/managing-deadlock-in-databases-418i</link>
      <guid>https://dev.to/idadelveloper/managing-deadlock-in-databases-418i</guid>
      <description>&lt;p&gt;It is common knowledge that databases are meant for storing data and it is the Database Management System (DBMS) that is in charge of controlling how data is stored, retrieved, and edited. You have probably written a program that accessed data from a database. What are the chances there wouldn't be any conflicts when trying to access this data? &lt;/p&gt;

&lt;h2&gt;
  
  
  What is deadlock?
&lt;/h2&gt;

&lt;p&gt;Deadlock is a common concept when dealing with operating systems but not necessarily limited to operating systems. Imagine you are hungry and go to the kitchen to get food. Turns out your sibling is already by the pot and wants to serve themselves. But there is a problem, you are holding the only clean plate available but wouldn't be able to get food unless your sibling is done. Your sibling needs a plate in order to serve themselves food but you wouldn't give up your plate. Neither will your sibling leave the pot unless they get a plate. You need the pot to get food but your sibling is with the pot. Your sibling needs a plate to get food but you are with the plate. This is a "deadlock" kind of scenario. Deadlock is a situation where a computer process waits for a resource which is being assigned or used by another process. &lt;/p&gt;

&lt;p&gt;In databases, a deadlock occurs when multiple transactions are waiting for the release of resources which leads a situation where neither can proceed. Deadlocks are not very frequent in databases but aren't inevitable. In the context of a database, a &lt;strong&gt;lock&lt;/strong&gt; is a mechanism used to control access to a resource, such as a data row, table, or page. Locks are employed to ensure the consistency and integrity of the database by preventing multiple transactions from simultaneously modifying the same resource. When multiple transactions are involved, and they are waiting for each other to release locks, it can lead to a deadlock.&lt;/p&gt;

&lt;p&gt;Here's a simple example to illustrate a deadlock scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transaction A holds a lock on Resource X and is waiting for Resource Y.&lt;/li&gt;
&lt;li&gt;Transaction B holds a lock on Resource Y and is waiting for Resource X.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to manage deadlocks in databases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deadlock Prevention:&lt;/strong&gt; Like they say &lt;em&gt;"Prevention is better than cure"&lt;/em&gt;. In order for this to happen, there should be an order in which transactions are being carried out. One transaction should wait for the other to release the lock before it can begin. There should be a hierarchy of acquiring locks ensuring these locks are requested in a consistent order. In addition, there should be a time limit for all transactions to acquire locks.This is ideal for small databases&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deadlock Detection:&lt;/strong&gt; Here, resources are allocated in such a  way that the deadlock never happens. The DBMS makes sure to assess the operations making sure there's no room for any deadlock else the transaction won't be executed. It involves periodically checking for deadlocks and this is perfect for very large databases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deadlock Resolution:&lt;/strong&gt; Once a deadlock is identified, there are 2 things that should be done - &lt;strong&gt;abort &amp;amp; rollback&lt;/strong&gt; and &lt;strong&gt;wait-die &amp;amp; wound-wait&lt;/strong&gt;. With &lt;em&gt;abort &amp;amp; rollback&lt;/em&gt;, one or more transactions that are involved in a deadlock are aborted in order to release their locks whereas in &lt;em&gt;wait-die &amp;amp; wound-wait&lt;/em&gt;, transactions are prioritized based on their timestamps. Younger transactions requesting locks held by older transactions are aborted meanwhile older transactions with locks held by younger transactions are forced to wait.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>database</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>TCP vs UDP</title>
      <dc:creator>Ida Delphine</dc:creator>
      <pubDate>Sun, 04 Feb 2024 14:53:46 +0000</pubDate>
      <link>https://dev.to/idadelveloper/tcp-vs-udp-4cil</link>
      <guid>https://dev.to/idadelveloper/tcp-vs-udp-4cil</guid>
      <description>&lt;p&gt;Before we jump right into what TCP and UDP is all about, we have to first understand the &lt;strong&gt;&lt;em&gt;OSI (Opens Systems Interconnection)&lt;/em&gt; model&lt;/strong&gt;. Do you ever think about what happens under the hood for data to transfered from one computer to another over the internet? The OSI model is used to visualize how this data is transmitted. &lt;/p&gt;

&lt;p&gt;The OSI model comes in to abstract the way data is transmitted between different computers with different architectures. This OSI model is made up of 7 different layers; &lt;strong&gt;&lt;em&gt;Application layer, Presentation layer, Session layer, Transport layer, Network layer, Data link layer, Physical layer&lt;/em&gt;&lt;/strong&gt;. For data to be transmitted, it will pas through all these 7 layers starting from the application layer where there is human-computer interaction to the physical layer which transmits raw bits of data to a physical medium. Our key focal point will be the &lt;strong&gt;Transport Layer&lt;/strong&gt; where we will be dissecting TCP and UDP.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is TCP?
&lt;/h2&gt;

&lt;p&gt;TCP stands for &lt;strong&gt;Transmission Control Protocol&lt;/strong&gt; specifies how data should be broken down and sent until it reaches its destination. It works together with the IP (internet protocol). TCP determines how to break the data into packets and the IP is responsible for addressing and routing these data packets making sure it reaches the destination chronologically.&lt;br&gt;
Imagine you want to access a webpage from the browser. Once the HTTP request is made, the TCP is responsible for transmitting the html file to your browser by splitting it into various packages. These packages are numbered and sent to your browser where they will assembled back to the html file for your viewing.&lt;br&gt;
It is worth noting TCP is connection-oriented where before the data is split into packets and routed, a connection between the source and destination is established. This connection is known as a &lt;strong&gt;handshake&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is UDP?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;User Datagram Protocol&lt;/strong&gt; is another protocol used to transmit data across the internet. However, it is connectionless as there is no formal connection established between the sender and receiver before the data is transmitted. UDP sends data packets directly to the computer without any connection between the two.&lt;/p&gt;

&lt;h2&gt;
  
  
  TCP vs UDP
&lt;/h2&gt;

&lt;p&gt;Comparatively, UDP is faster in terms of transmitting data than TCP whereas TCP is more reliable in the sense that the data is certainly going to reach its destination intact. TCP is slower because it takes time establishing the connection and if there's any data loss along the line a request will be made to obtain the missing data packet. They both have their strengths and weaknesses. UDP is commonly used in time-sensitive communications where packet loss is not a big deal and it's preferable than waiting e.g live streaming. TCP is ideal for scenarios where the data must be received intact without any data loss or alteration eg emails.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;NB&lt;/strong&gt;: It is worth noting the OSI model doesn't apply to the current internet and it's the &lt;strong&gt;TCP/IP&lt;/strong&gt; model which is currently used. The TCP/IP model comes from merging some of the layers of the OSI model.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>networking</category>
    </item>
  </channel>
</rss>
