<?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: Van_mai</title>
    <description>The latest articles on DEV Community by Van_mai (@van_mai).</description>
    <link>https://dev.to/van_mai</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%2F2865975%2Ff1799ef1-fdc9-46bb-9ee9-56ae32d5ef8b.jpg</url>
      <title>DEV Community: Van_mai</title>
      <link>https://dev.to/van_mai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/van_mai"/>
    <language>en</language>
    <item>
      <title>#Weather App with fantastic animations Tutorial for Beginners</title>
      <dc:creator>Van_mai</dc:creator>
      <pubDate>Sat, 01 Mar 2025 01:28:21 +0000</pubDate>
      <link>https://dev.to/van_mai/weather-app-with-fantastic-animations-tutorial-for-beginners-2fpi</link>
      <guid>https://dev.to/van_mai/weather-app-with-fantastic-animations-tutorial-for-beginners-2fpi</guid>
      <description>&lt;h2&gt;
  
  
  Weather App Tutorial for Beginners
&lt;/h2&gt;

&lt;p&gt;Hey everyone! Today, I will teach you how to create a weather app with some fantastic animations using JavaScript. Let’s dive in step by step!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2am9kdn6ikewx3x746ko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2am9kdn6ikewx3x746ko.png" alt="Image description" width="800" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Setting Up the Weather API
&lt;/h2&gt;

&lt;p&gt;This app will use the &lt;a href="https://openweathermap.org/api" rel="noopener noreferrer"&gt;OpenWeatherMap API&lt;/a&gt;. So, make sure your API key is ready. You can visit the OpenWeatherMap website to get your free API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create the Weather App HTML
&lt;/h2&gt;

&lt;p&gt;Here’s a simple structure for your weather app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;html
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&amp;gt;
    &amp;lt;link
        href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&amp;amp;family=Roboto:wght@300;400;500;700;900&amp;amp;display=swap"
        rel="stylesheet"&amp;gt;
    &amp;lt;link rel="stylesheet" href="weather-app.css"&amp;gt;
    &amp;lt;title&amp;gt;Weather App&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;script src="https://kit.fontawesome.com/7c8801c017.js" crossorigin="anonymous"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="weather-app.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We create the following divs: .container, .search-box, .not-found, .weather-box, and .weather-details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="container"&amp;gt;
    &amp;lt;div class="search-box"&amp;gt;
        &amp;lt;i class="fa-solid fa-location-dot"&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;input type="text" placeholder="Enter your location"&amp;gt;
        &amp;lt;button class="fa-solid fa-magnifying-glass"&amp;gt;&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class="not-found"&amp;gt;
        &amp;lt;img src="images/404.png"&amp;gt;
        &amp;lt;p&amp;gt;Oops! Invalid location&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class="weather-box"&amp;gt;
        &amp;lt;img src=""&amp;gt;
        &amp;lt;p class="temperature"&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;p class="description"&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div class="weather-details"&amp;gt;
        &amp;lt;div class="humidity"&amp;gt;
            &amp;lt;i class="fa-solid fa-water"&amp;gt;&amp;lt;/i&amp;gt;
            &amp;lt;div class="text"&amp;gt;
                &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                &amp;lt;p&amp;gt;Humidity&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class="wind"&amp;gt;
            &amp;lt;i class="fa-solid fa-wind"&amp;gt;&amp;lt;/i&amp;gt;
            &amp;lt;div class="text"&amp;gt;
                &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                &amp;lt;p&amp;gt;Wind Speed&amp;lt;/p&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztalkl4911k3ycs6ryhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztalkl4911k3ycs6ryhi.png" alt="Image description" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 2: Create the Weather App CSS
&lt;/h1&gt;

&lt;p&gt;Here’s the basic CSS to get you started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* {
    margin: 0;
    padding: 0;
    border: 0;
    outline: 0;
    box-sizing: border-box;
}

body {
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #06283D;
}

.container {
    position: relative;
    width: 400px;
    height: 105px;
    background: #fff;
    padding: 28px 32px;
    overflow: hidden;
    border-radius: 18px;
    font-family: Arial, sans-serif;
    transition: 0.6s ease-out;
}

.search-box {
    width: 100%;
    height: min-content;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.search-box input {
    color: #06283d;
    width: 80%;
    font-size: 25px;
    font-weight: 500;
    text-transform: uppercase;
    padding-left: 32px;
}

.search-box ::placeholder {
    font-size: 20px;
    font-weight: 500;
    color: #06283d;
    text-transform: capitalize;
}

.search-box button {
    cursor: pointer;
    width: 50px;
    height: 50px;
    color: #06283D;
    background: #dff6ff;
    border-radius: 50%;
    font-size: 25px;
    transition: 0.4s ease;
}

.search-box button:hover {
    color: #fff;
    background: #06283D;
}

.weather-box {
    text-align: center;
}

.weather-box img {
    width: 60%;
    margin-top: 30px;
}

.weather-box .temperature {
    font-size: 4rem;
    font-weight: 800;
    color: #06283D;
    position: relative;
    margin-top: 30px;
    margin-left: -16px;
}

.weather-box .temperature span {
    position: absolute;
    margin-left: 4px;
    font-size: 1.5rem;
}

.weather-box .description {
    font-size: 22px;
    font-weight: 500;
    color: #06283D;
    text-transform: capitalize;
}

.weather-details {
    width: 100%;
    display: flex;
    justify-content: space-between;
    margin-top: 30px;
}

.weather-details .humidity, .weather-details .wind {
    display: flex;
    align-items: center;
    width: 50%;
    height: 100px;
}

.weather-details .humidity {
    padding-right: 20px;
    justify-content: flex-start;
}

.weather-details .wind {
    padding-right: 20px;
    justify-content: flex-end;
}

.weather-details i {
    color: #06283D;
    font-size: 26px;
    margin-right: 10px;
    margin-top: 6px;
}

.weather-details span {
    font-size: 22px;
    font-weight: 500;
    color: #06283D;
}

.weather-details p {
    font-size: 14px;
    font-weight: 500;
    color: #06283D;
}

.not-found {
    width: 100%;
    text-align: center;
    margin-top: 50px;
    scale: 0;
    opacity: 0;
    display: none;
}

.not-found img {
    width: 70%;
}

.not-found p {
    color: #06283D;
    font-size: 22px;
    font-weight: 500;
    margin-top: 12px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Important:
&lt;/h3&gt;

&lt;p&gt;To add animation, you can use the fadeIn animation to make the app more dynamic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.weather-box, .weather-details {
    scale: 0;
    opacity: 0;
}

.fadeIn {
    animation: 0.5s fadeIn forwards;
    animation-delay: 0.5s;
}

@keyframes fadeIn {
    to {
        scale: 1;
        opacity: 1;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t7rcigyfmpigl987933.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t7rcigyfmpigl987933.png" alt="Image description" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 3: Create the Weather App JavaScript
&lt;/h1&gt;

&lt;p&gt;Now it’s time to bring the app to life with JavaScript. You’ll need to integrate with the OpenWeatherMap API. Below is the starting point for your JS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const container = document.querySelector('.container');
const search = document.querySelector('.search-box button');
const weatherBox = document.querySelector('.weather-box');
const weatherDetails = document.querySelector('.weather-details');
const error404 = document.querySelector('.not-found');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you’ll need to set up the fetch API to get weather data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;search.addEventListener('click', () =&amp;gt; {
    const key_API = `f62b1ae7f33dea18b1279c2e658a1d63`;
    const city = document.querySelector('.search-box input').value;

    if (city === ``) return;

    fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&amp;amp;units=metric&amp;amp;appid=${key_API}`)
        .then(response =&amp;gt; response.json())
        .then(json =&amp;gt; {
            if (json.cod === `404`) {
                container.style.height = `400px`;
                weatherBox.style.display = `none`;
                weatherDetails.style.display = `none`;
                error404.style.display = `block`;
                error404.classList.add(`fadeIn`);
                return;
            }

            const image = document.querySelector('.weather-box img');
            const temperature = document.querySelector('.weather-box .temperature');
            const description = document.querySelector('.weather-box .description');
            const humidity = document.querySelector('.weather-details .humidity span');
            const wind = document.querySelector('.weather-details .wind span');

            switch (json.weather[0].main) {
                case `Clear`:
                    image.src = `images/clear.png`;
                    break;
                case `Rain`:
                    image.src = `images/rain.png`;
                    break;
                case `Snow`:
                    image.src = `images/snow.png`;
                    break;
                case `Clouds`:
                    image.src = `images/cloud.png`;
                    break;
                case `Haze`:
                    image.src = `images/mist.png`;
                    break;
                default:
                    image.src = ``;
            }

            temperature.innerHTML = `${parseInt(json.main.temp)}&amp;amp;deg;C`;
            description.innerHTML = `${json.weather[0].main}`;
            humidity.innerHTML = `${json.main.humidity}%`;
            wind.innerHTML = `${json.wind.speed} Km/h`;

            weatherBox.style.display = ``;
            weatherDetails.style.display = ``;
            weatherBox.classList.add(`fadeIn`);
            weatherDetails.classList.add(`fadeIn`);
            container.style.height = `590px`;
        });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That’s it! You now have a fully functional weather app. Keep improving it by adding more features like more detailed forecasts, custom icons, or even a background image that changes based on the weather conditions.&lt;/p&gt;

&lt;p&gt;If you found this tutorial helpful, feel free to connect with me for more web development tips and tricks.&lt;/p&gt;

&lt;p&gt;Here are the full code. &lt;/p&gt;

&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&amp;gt;
    &amp;lt;link
        href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800;900&amp;amp;family=Roboto:wght@300;400;500;700;900&amp;amp;display=swap"
        rel="stylesheet"&amp;gt;
    &amp;lt;link rel="stylesheet" href="weather-app.css"&amp;gt;
    &amp;lt;title&amp;gt;Weather-App&amp;lt;/title&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

    &amp;lt;div class="container"&amp;gt;
        &amp;lt;div class="search-box"&amp;gt;
            &amp;lt;i class="fa-solid fa-location-dot"&amp;gt;&amp;lt;/i&amp;gt;
            &amp;lt;input type="text" placeholder="Enter your location"&amp;gt;
            &amp;lt;button class="fa-solid fa-magnifying-glass"&amp;gt;&amp;lt;/button&amp;gt;             
        &amp;lt;/div&amp;gt;
        &amp;lt;div class="not-found"&amp;gt;
            &amp;lt;img src="images/404.png"&amp;gt;
            &amp;lt;p&amp;gt;Oops! Invalid location&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class="weather-box"&amp;gt;
            &amp;lt;img src=""&amp;gt;
            &amp;lt;p class="temperature"&amp;gt;&amp;lt;/p&amp;gt;
            &amp;lt;p class="description"&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div class="weather-details"&amp;gt;
            &amp;lt;div class="humidity"&amp;gt;
                &amp;lt;i class="fa-solid fa-water"&amp;gt;&amp;lt;/i&amp;gt;
                &amp;lt;div class="text"&amp;gt;
                    &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                    &amp;lt;p&amp;gt;Humidity&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;

            &amp;lt;div class="wind"&amp;gt;
                &amp;lt;i class="fa-solid fa-wind"&amp;gt;&amp;lt;/i&amp;gt;
                &amp;lt;div class="text"&amp;gt;
                    &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;
                    &amp;lt;p&amp;gt;Wind Speed&amp;lt;/p&amp;gt;
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;



        &amp;lt;/div&amp;gt;



    &amp;lt;/div&amp;gt;





&amp;lt;/body&amp;gt;

&amp;lt;script src="https://kit.fontawesome.com/7c8801c017.js" crossorigin="anonymous"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src="weather-app.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*{
    margin: 0;
    padding: 0;
    border: 0;
    outline: 0;
    box-sizing: border-box;

}

body{
    height: 100vh;
    display: flex;
    align-items:center;
    justify-content:center;
    background: #06283D

}

.container{
    position: relative;
    width: 400px;
    height: 105px;
    background: #fff;
    padding: 28px 32px;
    overflow: hidden;
    border-radius: 18px;
    font-family: Arial, sans-serif;
    transition: 0.6s ease-out; 
}

.search-box{
    width: 100%;
    height: min-content;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.search-box input{
    color: #06283d;
    width: 80%;
    font-size: 25px;
    font-weight: 500;
    text-transform: uppercase;
    padding-left: 32px;

}

.search-box ::placeholder{
    font-size: 20px;
    font-weight: 500;
    color: #06283d;
    text-transform: capitalize;

}

.search-box button{
    cursor: pointer;
    width: 50px;
    height: 50px;
    color: #06283D;
    background: #dff6ff;
    border-radius: 50%;
    font-size: 25px;
    transition: 0.4s ease;

}

.search-box button:hover{
    color: #fff;
    background: #06283D;
}

.weather-box{
    text-align: center;
}

.weather-box img{
    width: 60%;
    margin-top: 30px;
}

.weather-box .temperature{
    font-size: 4rem;
    font-weight: 800;
    color: #06283D;
    position: relative;
    margin-top: 30px;
    margin-left: -16px;
}

.weather-box .temperature span{
    position: absolute;
    margin-left: 4px;
    font-size: 1.5rem;

}

.weather-box .description{
    font-size: 22px;
    font-weight: 500;
    color: #06283D;
    text-transform: capitalize;
}

.weather-details{
    width: 100%;
    display: flex;
    justify-content: space-between;
    margin-top: 30px;

}

.weather-details .humidity, .weather-details .wind{
    display: flex;
    align-items: center;
    width: 50%;
    height: 100px;
}

.weather-details .humidity{
    padding-right: 20px;
    justify-content: flex-start;
}

.weather-details .wind{
    padding-right: 20px;
    justify-content: flex-end;
}

.weather-details i{
    color: #06283D;
    font-size: 26px;
    margin-right: 10px;
    margin-top: 6px;

}

.weather-details span{
    font-size: 22px;
    font-weight: 500;
    color: #06283D;
}

.weather-details p{
    font-size: 14px;
    font-weight: 500;
    color: #06283D;
}


.not-found{
    width: 100%;
    text-align: center;
    margin-top: 50px;
    scale: 0;
    opacity: 0;
    display: none;
}

.not-found img{
    width: 70%;

}

.not-found p{
    color: #06283D;
    font-size: 22px;
    font-weight: 500;
    margin-top: 12px;

}

.weather-box, .weather-details{
    scale: 0;
    opacity: 0;
}

.fadeIn{
    animation: 0.5s fadeIn forwards;
    animation-delay: 0.5s;

}

@keyframes fadeIn{
    to {
        scale: 1;
        opacity: 1;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const container = document.querySelector('.container');
const search = document.querySelector('.search-box button');
const weatherBox = document.querySelector('.weather-box');
const weatherDetails = document.querySelector('.weather-details');
const error404 = document.querySelector('.not-found');

search.addEventListener('click', () =&amp;gt; {
    const key_API=`f62b1ae7f33dea18b1279c2e658a1d63`
    const city = document.querySelector('.search-box input').value;

    if (city === ``)
        return;

    fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&amp;amp;units=metric&amp;amp;appid=${key_API}`)
    .then(response =&amp;gt; response.json()).then(json =&amp;gt; {

        if (json.cod === `404`){
            container.style.height = `400px`;
            weatherBox.style.display = `none`;
            weatherDetails.style.display = `none`;
            error404.style.display = `block`;
            error404.classList.add(`fadeIn`);
            return;

        }

        error404.style.display = `none`;
        error404.classList.remove(`fadeIn`);

        const image = document.querySelector(`.weather-box img`);
        const temperature = document.querySelector(`.weather-box .temperature`);
        const description = document.querySelector(`.weather-box .description`);
        const humidity= document.querySelector(`.weather-details .humidity span`);
        const wind = document.querySelector(`.weather-details .wind span`);

        switch (json.weather[0].main){
            case `Clear`:
                image.src = `images/clear.png`;
                break;
            case `Rain`:
                image.src = `images/rain.png`;
                break;
            case `Snow`:
                image.src = `images/snow.png`;
                break;
            case `Clouds`:
                image.src = `images/cloud.png`;
                break;
            case `Haze`:
                image.src = `images/mist.png`;
                break;
            default:
                image.src = ``; 
        }

        temperature.innerHTML = `${parseInt(json.main.temp)}&amp;amp;deg;C`;
        description.innerHTML = `${json.weather[0].main}`;
        humidity.innerHTML = `${json.main.humidity}%`;
        wind.innerHTML = `${json.wind.speed}Km/h`;

        weatherBox.style.display = ``;
        weatherDetails.style.display = ``;
        weatherBox.classList.add(`fadeIn`);
        weatherDetails.classList.add(`fadeIn`);
        container.style.height = `590px`;

    })

})


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Scraping NHK News Web Easy with Python: A Step-by-Step Guide</title>
      <dc:creator>Van_mai</dc:creator>
      <pubDate>Sat, 15 Feb 2025 09:37:38 +0000</pubDate>
      <link>https://dev.to/van_mai/scraping-nhk-news-web-easy-with-python-a-step-by-step-guide-4e12</link>
      <guid>https://dev.to/van_mai/scraping-nhk-news-web-easy-with-python-a-step-by-step-guide-4e12</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Scraping NHK News Web Easy with Python
&lt;/h1&gt;

&lt;p&gt;If you are learning Japanese. NHK News Web Easy is a very nice.   Want to extract real-time news from NHK News Web Easy using Python?** In this tutorial, we'll use &lt;strong&gt;Selenium + BeautifulSoup&lt;/strong&gt; to scrape the latest articles, save them in a structured format, and even export them as a Word document. 📝&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;By the end of this tutorial, you will learn how to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch and parse &lt;strong&gt;dynamic&lt;/strong&gt; web pages using &lt;strong&gt;Selenium&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Extract &lt;strong&gt;news titles, links, and content&lt;/strong&gt; with &lt;strong&gt;BeautifulSoup&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Export data into a structured &lt;strong&gt;Word document&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid getting blocked&lt;/strong&gt; and optimize your scraper 🚀&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🌍 Demo: What We Are Building&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code, &lt;strong&gt;here’s what our scraper will do:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visit NHK News Web Easy&lt;/strong&gt; 🔍&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract the latest news headlines &amp;amp; links&lt;/strong&gt; 📄&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scrape the full article content&lt;/strong&gt; 📰&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save the data into a structured Word file&lt;/strong&gt; 📝&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  💡 Here’s an example of the output file:
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🛠️ Step 1: Install Required Packages&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We will use the following Python libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requests&lt;/code&gt;: To fetch webpage content&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selenium&lt;/code&gt;: To handle dynamic JavaScript-loaded content&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bs4 (BeautifulSoup)&lt;/code&gt;: To parse HTML&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docx&lt;/code&gt;: To save news articles into a Word document&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Install them using (Mac):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install requests selenium bs4 python-docx webdriver-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  **🛠️ Step 2:Fetching the NHK News Web Easy Homepage
&lt;/h2&gt;

&lt;p&gt;Since NHK News Web Easy loads content dynamically using JavaScript, we need Selenium to handle the page rendering.&lt;/p&gt;

&lt;p&gt;Here’s how to launch a headless Chrome browser and fetch the homepage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time

# Configure Selenium WebDriver
chrome_options = Options()
chrome_options.add_argument("--headless")  # Run in background
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")

# Launch the WebDriver
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)

# Visit NHK News Web Easy
NHK_URL = "https://www3.nhk.or.jp/news/easy/"
driver.get(NHK_URL)

# Wait for JavaScript to load content
time.sleep(5)

# Get the HTML source code
html = driver.page_source
driver.quit()

print(html[:500])  # Display first 500 characters of the HTML
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ What this does:&lt;br&gt;
    • Starts a headless Chrome browser to load JavaScript content&lt;br&gt;
    • Fetches the entire rendered webpage (including dynamically loaded articles)&lt;/p&gt;
&lt;h2&gt;
  
  
  🔍 Step 3: Extracting News Links
&lt;/h2&gt;

&lt;p&gt;Once we have the full page source, we use BeautifulSoup to extract all news articles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from bs4 import BeautifulSoup

# Parse HTML with BeautifulSoup
soup = BeautifulSoup(html, "html.parser")

# Extract news article links
articles = soup.select("article.news-list__item a")
news_links = ["https://www3.nhk.or.jp" + a["href"] for a in articles]

print(f"Found {len(news_links)} news articles.")
print(news_links[:5])  # Preview first 5 links
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ This code:&lt;br&gt;
    • Finds all article links on the homepage&lt;br&gt;
    • Extracts absolute URLs for further scraping&lt;/p&gt;
&lt;h2&gt;
  
  
  📰 Step 4: Scraping Full Article Content
&lt;/h2&gt;

&lt;p&gt;Now, let’s fetch each article and extract title + content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

for news_url in news_links[:5]:  # Limit to 5 articles
    response = requests.get(news_url, headers=headers)
    response.encoding = "utf-8"

    news_soup = BeautifulSoup(response.text, "html.parser")
    title = news_soup.find("h1", class_="article-title").text.strip()
    content_blocks = news_soup.find("div", class_="article-body")

    content = "\n".join([p.text.strip() for p in content_blocks.find_all("p")]) if content_blocks else "No content available."

    print(f"📌 {title}\n{content[:200]}...\n")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚀 Conclusion
&lt;/h2&gt;

&lt;p&gt;✅ This script:&lt;br&gt;
    • Fetches each news page&lt;br&gt;
    • Extracts the title and article body&lt;br&gt;
    • Prints a preview of the first 200 characters&lt;/p&gt;
&lt;h2&gt;
  
  
  📂 Step 5: Saving News to Word
&lt;/h2&gt;

&lt;p&gt;Finally, let’s store the scraped articles in a structured Word document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from docx import Document

doc = Document()
doc.add_heading("NHK News Web Easy Articles", level=1)

for news_url in news_links[:5]:  # Limit to 5 articles
    response = requests.get(news_url, headers=headers)
    response.encoding = "utf-8"
    news_soup = BeautifulSoup(response.text, "html.parser")

    title = news_soup.find("h1", class_="article-title").text.strip()
    content_blocks = news_soup.find("div", class_="article-body")
    content_jp = "\n".join([p.text.strip() for p in content_blocks.find_all("p")]) if content_blocks else "No content."

    doc.add_heading(title, level=2)
    doc.add_paragraph(f"Japanese Text:\n{content_jp}")
    doc.add_paragraph("-" * 50)

doc.save("NHK_News.docx")
print("✅ NHK_News.docx saved successfully!")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎯 Now you have a fully automated news scraper!&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Conclusion
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• 📡 Selenium fetches dynamically loaded content
• 🔍 BeautifulSoup extracts articles
• 📝 python-docx saves content in Word format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;“This is the final code. You can change the number 5 in for news_url in news_links[:5]: to any other number to adjust the number of news articles you want to generate.”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
import time
from bs4 import BeautifulSoup
from docx import Document

# Fake browser request to prevent NHK from blocking
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

# Launch Selenium
chrome_options = Options()
chrome_options.add_argument("--headless")  # Run in the background
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("start-maximized")
chrome_options.add_argument("disable-infobars")
chrome_options.add_argument("--disable-extensions")
service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service, options=chrome_options)

# Access NHK Easy News
NHK_URL = "https://www3.nhk.or.jp/news/easy/"
driver.get(NHK_URL)

# Wait 5 seconds for JavaScript to load
time.sleep(5)

# Get the page HTML
html = driver.page_source
driver.quit()  # Close the browser

# Parse the HTML
soup = BeautifulSoup(html, "html.parser")

# Extract news links
articles = soup.select("article.news-list__item a")
news_links = ["https://www3.nhk.or.jp" + a["href"] for a in articles]

print(f"Retrieved {len(news_links)} news articles")
if not news_links:
    print("❌ No news found, please check the HTML structure!")
    exit()

# Create a Word document
doc = Document()
doc.add_heading("NHK News Web Easy Article Collection", level=1)

for news_url in news_links[:20]:  # Scrape only the first 20 news articles
    print(f"Fetching: {news_url}")

    # Retrieve the news page
    response = requests.get(news_url, headers=headers)
    response.encoding = "utf-8"  # Ensure UTF-8 decoding
    news_soup = BeautifulSoup(response.text, "html.parser")

    # Get news title (updated class)
    title_tag = news_soup.find("h1", class_="article-title")
    title = title_tag.text.strip() if title_tag else "No Title"

    # Get news content (updated class)
    content_blocks = news_soup.find("div", class_="article-body")
    if content_blocks:
        content_jp = "\n".join([p.text.strip() for p in content_blocks.find_all("p")])
    else:
        content_jp = "No Content"

    print(f"✅ Successfully retrieved: {title}")

    # Write to Word document
    doc.add_heading(title, level=2)
    doc.add_paragraph(f"Original Japanese Text:\n{content_jp}")
    doc.add_paragraph("-" * 50)

# Save Word file
doc.save("NHK_News.docx")
print("✅ Article collection completed, saved as NHK_News.docx")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>webscraping</category>
      <category>selenium</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
