What’s the problem with parsing dynamic HTML content in Python and in general?
The problem is that when you request contents of a HTML page, you are presented HTML, CSS and scripts returned from the server. If the page is dynamic, what you get is only a couple of scripts that are meant to be interpreted by your browser that, in its turn, will eventually display HTML content for a user.
That leads us to the idea that we should first render the page and then grab its HTML. Also it should take some time to render the page since sometimes the content is quite “heavy” and it takes some time to load it.
So, along with pure Python we should use some kind of UI component and in particular a Web View or some kind of Web frame.
One of the options is to use Qt for Python and to handle page rendering events and another one (which I honestly prefer more) is to use selenium for python.
So, let’s get down to writing some code but before that let’s elaborate and approach.
- Open web view with URL.
- Wait untill the page is loaded. Often the criteria here is a loaded div of some class.
- Grab the rendered HTML.
- Process it further using beautiful soup
You will need Chrome Web Driver to run the web view.
Also you will have to install selenium as well as libs from previous tutorial:
pip install selenium
So here is the Python code to parse dynamic content:
#import selenium compnents, urllib, beautiful soup from bs4 import BeautifulSoup from selenium import webdriver from urllib import urlopen from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By #url - the url to fetch dynamic content from. #delay - second for web view to wait #block_name - id of the tag to be loaded as criteria for page loaded state. def fetchHtmlForThePage(url, delay, block_name): #supply the local path of web driver. #in this example we use chrome driver browser = webdriver.Chrome('/Applications/chromedriver') #open the browser with the URL #a browser windows will appear for a little while browser.get(url) try: #check for presence of the element you're looking for element_present = EC.presence_of_element_located((By.ID, block_name)) WebDriverWait(browser, delay).until(element_present) #unless found, catch the exception except TimeoutException: print "Loading took too much time!" #grab the rendered HTML html = browser.page_source #close the browser browser.quit() #return html return html #call the fetching function we created html = fetchHtmlForThePage(url, 5, 're-Searchresult') #grab HTML document soup = BeautifulSoup(html) #process it further as you wish..... #..... processFetchedUrls(soup, path)