kesma

24ur python scrape for keyword for 60 past days

May 13th, 2025 (edited)
114
0
Never
13
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.31 KB | Source Code | 0 0
  1. #!/usr/bin/env python3
  2. """
  3. Stream‐based script to count daily 24ur.com articles mentioning “Dončić” over the past 60 days,
  4. writing two CSVs as soon as each day’s URLs are fully processed:
  5.  
  6.  • Stats CSV: date,count                  (`doncic_article_counts.csv`)
  7.  • URLs  CSV:  date,url                    (`doncic_article_urls.csv`)
  8.  
  9. Algorithm:
  10. 1. Remove old output files and write headers.
  11. 2. Crawl sitemap pages from 1357 down to 1.
  12. 3. Within each page, scan URLs in reverse order (so dates go newest→oldest).
  13. 4. Track `current_date`; for each URL:
  14.      - When the date changes, flush stats+URLs for the previous date.
  15.      - Then start counting for the new date.
  16. 5. For each URL whose **main article text** (only `<p>` paragraphs) contains “Dončić” at least once:
  17.      - Increment that date’s counter.
  18.      - Append the URL to that date’s URL CSV.
  19. 6. After all pages, flush the last date’s data.
  20.  
  21. Requires:
  22.    pip install requests beautifulsoup4 tqdm
  23. """
  24. import os
  25. import csv
  26. import time
  27. import unicodedata
  28. import requests
  29. import xml.etree.ElementTree as ET
  30. from datetime import datetime, timedelta
  31. from bs4 import BeautifulSoup
  32. from requests.exceptions import HTTPError
  33. from tqdm import tqdm
  34.  
  35. # ——— Configuration ———
  36. KEYWORD = "Dončić"
  37. KEYWORD_ASCII = (
  38.     unicodedata.normalize("NFKD", KEYWORD)
  39.     .encode("ascii", "ignore")
  40.     .decode()
  41.     .lower()
  42. )
  43. BASE_SITEMAP_PAGE = "https://www.24ur.com/sitemaps/sites/1/pages/{}"
  44. FIRST_PAGE = 1357
  45. LAST_PAGE = 1
  46. WINDOW_DAYS = 60
  47. STATS_CSV = "doncic_article_counts.csv"
  48. URLS_CSV  = "doncic_article_urls.csv"
  49. REQUEST_DELAY = 0.5  # seconds between HTTP requests
  50. # ————————————————————
  51.  
  52. def parse_iso_date(s: str) -> datetime.date:
  53.     return datetime.fromisoformat(s).date()
  54.  
  55. def fetch_xml(url: str) -> ET.Element:
  56.     resp = session.get(url)
  57.     resp.raise_for_status()
  58.     return ET.fromstring(resp.text)
  59.  
  60. def extract_main_text(html: str) -> str:
  61.     """
  62.    Parse the HTML with BeautifulSoup, pull out only the <p> tags
  63.    (which hold the article paragraphs), join them, then normalize
  64.    to ASCII lowercase for matching.
  65.    """
  66.     soup = BeautifulSoup(html, "html.parser")
  67.     paras = [p.get_text(" ") for p in soup.find_all("p")]
  68.     text = " ".join(paras)
  69.     return unicodedata.normalize("NFKD", text) \
  70.                       .encode("ascii", "ignore") \
  71.                       .decode() \
  72.                       .lower()
  73.  
  74. if __name__ == "__main__":
  75.     # Prepare window
  76.     today = datetime.now().date()
  77.     start_date = today - timedelta(days=WINDOW_DAYS)
  78.  
  79.     # Remove old outputs, write headers
  80.     for path, header in [
  81.         (STATS_CSV, ["date", "count"]),
  82.         (URLS_CSV,  ["date", "url"])
  83.     ]:
  84.         if os.path.exists(path):
  85.             os.remove(path)
  86.         with open(path, "w", newline="", encoding="utf-8") as f:
  87.             csv.writer(f).writerow(header)
  88.  
  89.     session = requests.Session()
  90.     current_date = None
  91.     current_count = 0
  92.  
  93.     # Crawl from page 1357 → 1
  94.     for page_num in tqdm(range(FIRST_PAGE, LAST_PAGE - 1, -1),
  95.                          desc="Sitemap pages", unit="page"):
  96.         sitemap_url = BASE_SITEMAP_PAGE.format(page_num)
  97.         try:
  98.             root = fetch_xml(sitemap_url)
  99.         except HTTPError as e:
  100.             if e.response is not None and e.response.status_code == 404:
  101.                 continue
  102.             break
  103.  
  104.         url_elems = root.findall(".//{*}url")
  105.         if not url_elems:
  106.             continue
  107.  
  108.         # Process URLs in reverse order (end→start)
  109.         for url_elem in tqdm(reversed(url_elems),
  110.                              desc=f" Articles (pg {page_num})",
  111.                              unit="url", leave=False):
  112.             loc = url_elem.find("{*}loc").text
  113.             if not loc.startswith("https://www.24ur.com/"):
  114.                 continue
  115.  
  116.             pub_date = parse_iso_date(url_elem.find("{*}lastmod").text)
  117.             if pub_date < start_date or pub_date > today:
  118.                 continue
  119.  
  120.             # Initialize on first URL
  121.             if current_date is None:
  122.                 current_date = pub_date
  123.  
  124.             # When date rolls over, flush previous date
  125.             if pub_date != current_date:
  126.                 with open(STATS_CSV, "a", newline="", encoding="utf-8") as sf:
  127.                     csv.writer(sf).writerow([current_date.isoformat(), current_count])
  128.                 current_date = pub_date
  129.                 current_count = 0
  130.  
  131.             # Fetch article and search keyword in main text
  132.             try:
  133.                 r = session.get(loc); r.raise_for_status()
  134.             except:
  135.                 continue
  136.  
  137.             main_text = extract_main_text(r.text)
  138.             if KEYWORD_ASCII in main_text:
  139.                 current_count += 1
  140.                 with open(URLS_CSV, "a", newline="", encoding="utf-8") as uf:
  141.                     csv.writer(uf).writerow([pub_date.isoformat(), loc])
  142.  
  143.             time.sleep(REQUEST_DELAY)
  144.  
  145.     # Flush last date if any
  146.     if current_date is not None:
  147.         with open(STATS_CSV, "a", newline="", encoding="utf-8") as sf:
  148.             csv.writer(sf).writerow([current_date.isoformat(), current_count])
  149.  
  150.     print("Done! Outputs written:")
  151.     print("  ", STATS_CSV)
  152.     print("  ", URLS_CSV)
Advertisement
Comments
  • kesma
    1 year
    Comment was deleted
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Myrwegyx
    25 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • User was banned
  • Halrunot
    10 days
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=klkkvcnjot
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment