Skip to content

Download script is changed to add all quarters of data - #2115

Open
Krishnam24maheshwari wants to merge 2 commits into
datacommonsorg:masterfrom
Krishnam24maheshwari:new_branch
Open

Download script is changed to add all quarters of data#2115
Krishnam24maheshwari wants to merge 2 commits into
datacommonsorg:masterfrom
Krishnam24maheshwari:new_branch

Conversation

@Krishnam24maheshwari

Copy link
Copy Markdown

No description provided.

@google-cla

google-cla Bot commented Jul 28, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Brazil SIDRA IBGE download script, replacing the Selenium-based browser automation with direct API calls using the requests library and reshaping the data into Excel files using pandas. The review feedback recommends improving performance, security, and robustness by using a global requests.Session with connection pooling and retries, re-enabling SSL verification, and adding explicit guard checks to safely parse the API responses.

Comment on lines 15 to +24
import os
import re
import time
import glob
import requests
import urllib3
import pandas as pd
from absl import app, logging, flags
from pathlib import Path

# Import specific Selenium exceptions
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.support import expected_conditions as EC

# Suppress SSL InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Using requests.get repeatedly in a loop (via fetch_aggregate_series) is inefficient because it opens and closes a new connection for every request, performing a full TCP and SSL handshake each time. Since this script makes hundreds of API calls, using a global requests.Session will enable connection pooling and keep-alive, significantly improving performance.

Additionally, configuring retries on this session will satisfy the requirement for robust downloading from unstable external sources, as specified in the general rules.

Finally, disabling SSL verification (verify=False) and suppressing warnings is a security risk as it exposes the script to Man-in-the-Middle (MitM) attacks. We have enabled SSL verification in the suggested session configuration.

import os
import time
import requests
import urllib3
import pandas as pd
from absl import app, logging, flags
from pathlib import Path
from requests.adapters import HTTPAdapter
from urllib3.util import Retry

# Configure a global session with retries and connection pooling
def get_robust_session():
    session = requests.Session()
    retries = Retry(
        total=10,
        backoff_factor=1,
        status_forcelist=[500, 502, 503, 504],
        raise_on_status=False
    )
    session.mount("https://", HTTPAdapter(max_retries=retries))
    return session

SESSION = get_robust_session()
References
  1. When downloading data from unstable or unreliable external sources, configure a higher number of retries (e.g., tries=10) to ensure download success, even if it results in a long cumulative wait time.

"""
url = "https://servicodados.ibge.gov.br/api/v3/agregados/6461/periodos"
headers = {"User-Agent": "Mozilla/5.0"}
res = requests.get(url, headers=headers, verify=False, timeout=30)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use the global SESSION object to perform the HTTP request. This enables connection pooling, automatic retries, and keeps SSL verification enabled.

Suggested change
res = requests.get(url, headers=headers, verify=False, timeout=30)
res = SESSION.get(url, headers=headers, timeout=30)

EC.element_to_be_clickable((By.CSS_SELECTOR, "ul.dropdown-menu li[data-item='0'] a"))
)
export_option.click()
r = requests.get(url, headers=headers, verify=False, timeout=30)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use the global SESSION object to perform the HTTP request. This enables connection pooling, automatic retries, and keeps SSL verification enabled.

Suggested change
r = requests.get(url, headers=headers, verify=False, timeout=30)
r = SESSION.get(url, headers=headers, timeout=30)

Comment on lines +111 to +113
data = r.json()
if not data or "resultados" not in data[0]:
return {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To prevent potential KeyError or TypeError when the API returns an unexpected dictionary or non-list response, explicitly verify that data is a non-empty list before accessing data[0]. This aligns with the preference for explicit guard checks over broad exception handling for nested data structures.

Suggested change
data = r.json()
if not data or "resultados" not in data[0]:
return {}
data = r.json()
if not isinstance(data, list) or not data or "resultados" not in data[0]:
return {}
References
  1. Prefer explicit guard checks over broad exception control flow (try...except) for handling nested data structures, as they are easier to reason about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant