I use this script to scrape the results of a SEDE page and return as a BeautifulSoup object.
A small twist is that if I don't use a SEDE query manually in the browser for a few days, then non-interactive downloads get empty results. (I suspect there is a robot test there.)
Rather than fixing the robot test issue, my workaround is to cache successfully downloaded pages, and use the cache when downloading is not working well.
import logging
import os
import requests
from bs4 import BeautifulSoup
BASE_DIR = os.path.dirname(__file__)
CACHE_DIR = os.path.join(BASE_DIR, '.cache')
def fetch_sede_soup(label, url):
def is_valid(soup):
for script in soup.findAll('script'):
if 'resultSets' in script.text:
return True
return False
if not os.path.isdir(CACHE_DIR):
os.mkdir(CACHE_DIR)
logging.info('fetching {} as {}'.format(label, url))
html = requests.get(url).text
soup = BeautifulSoup(html)
cache_path = os.path.join(CACHE_DIR, '{}.html'.format(label))
debug_cache_path = os.path.join(CACHE_DIR, '{}-debug.html'.format(label))
if is_valid(soup):
logging.info('updating cache')
with open(cache_path, 'w') as fh:
fh.write(html)
return soup
with open(debug_cache_path, 'w') as fh:
fh.write(html)
logging.warning('result not valid')
if os.path.exists(cache_path):
logging.info('using previous cache')
with open(cache_path) as fh:
return BeautifulSoup(fh)
Can this be written better?
In case it helps, here are some sample output files:
- sede-output.html - a successful download.
- sede-output-debug.html - a "failed" download (empty results).