Reputation: 497
I have a web scraping code that cannot find a table. My code looks like:
site = 'http://etfdb.com/compare/market-cap/'
hdr = {'User-Agent': 'Mozilla/5.0'}
req = Request(site, headers=hdr)
page = urlopen(req)
soup = BeautifulSoup(page)
table = soup.find('table', {"class":"table mm-mobile-table table-striped
table-bordered"})
The tables HTML looks like:
<table class="table mm-mobile-table table-striped table-bordered" data-
icons-prefix="fa" data-icons="{"columns":"fa-th"}" data-
striped="true" data-toggle="table">
but for some reason my code always returns table as none. I do not know why but any help would be appreciated. Thanks.
Upvotes: 3
Views: 5907
Reputation: 9440
The problem is that there is incorrect markup making large sections of the code commented out i.e
<!-->.
the fix was to replace these elements then parse the HTML.
from urllib2 import urlopen, Request
from bs4 import BeautifulSoup
site = 'http://etfdb.com/compare/market-cap/'
hdr = {'User-Agent': 'Mozilla/5.0'}
req = Request(site, headers=hdr)
res = urlopen(req)
rawpage = res.read()
page = rawpage.replace("<!-->", "")
soup = BeautifulSoup(page, "html.parser")
table = soup.find("table", {"class":"table mm-mobile-table table-striped table-bordered"})
print (table)
Tested on Python 2.7.12
from urllib.request import urlopen, Request
from bs4 import BeautifulSoup
site = 'http://etfdb.com/compare/market-cap/'
hdr = {'User-Agent': 'Mozilla/5.0'}
req = Request(site, headers=hdr)
res = urlopen(req)
rawpage = res.read().decode("utf-8")
page = rawpage.replace('<!-->', '')
soup = BeautifulSoup(page, "html.parser")
table = soup.find("table", {"class":"table mm-mobile-table table-striped table-bordered"})
print (table)
Tested on Python 3.5.2
Gives:
<table class="table mm-mobile-table table-striped table-bordered" data-icons='{"columns":"fa-th"}' data-icons-prefix="fa" data-striped="true" data-toggle="table"><thead><tr><th class="show-td" data-field="symbol">Symbol</th> <th class="show-td" data-field="name">Name</th> <th class="show-td" data-field="aum">AUM</th> <th class="show-td" data-field="avg-volume">Avg Volume</th></tr></thead><tbody><tr><td class="show-td" data-th="Symbol"><a href="/etf/SPY/">SPY</a></td> <td class="show-td" data-th="Name"><a href="/etf/SPY/">SPDR S&P 500 ETF</a></td> <td class="show-td" data-th="AUM">$236,737,519.17</td> <td class="show-td" data-th="Avg Volume">73,039,883</td></tr> <tr><td class="show-td" data-th="Symbol"><a href="/etf/IVV/">IVV</a></td> <td class="show-td" data-th="Name"><a href="/etf/IVV/">iShares Core S&P 500 ETF</a></td> <td class="show-td" data-th="AUM">$115,791,603.10</td> <td class="show-td" data-th="Avg Volume">3,502,931</td></tr> ...
Upvotes: 4
Reputation: 306
I don't know maybe it's because their code is not well-structured [deliberately] and BeautifulSoup couldn't parse it. But maybe this helps you:
import re # to extract table with regex
table_soup = BeautifulSoup( re.findall(r'<table.*>.*</table>', page.read())[0] )
Also you can investigate further with something like this:
for tag in soup.find_all():
if tag.name == 'div':
if str(tag).find("table-striped") > -1:
print repr( str(tag)[:100] )
To see which div
tags contain the table
, if any:
'<div class="mm-header">\n<div class="container">\n<div class="row">\n<div class="col-xs-12">\n<div class'
'<div class="container">\n<div class="row">\n<div class="col-xs-12">\n<div class="mm-user-links hidden-x'
'<div class="row mm-header-content">\n<div class="col-sm-4 mm-header-logos">\n<button class="navbar-tog'
'<div class="col-sm-4 mm-header-logos">\n<button class="navbar-toggle">\n<span class="fa fa-bars"></spa'
So I guess BeautifulSoup couldn't break down the last one into child tags.
Edit:
Sorry I forgot to add page.read()
to get page source first, see the second line again.
If you don't want to use regex, you can use a better parser rather than the default one: html5lib
First install it:
# pip install html5lib
The you can use it by:
soup = BeautifulSoup(page, 'html5lib')
Upvotes: 0
Reputation: 11985
You need to specify what exactly you want to parse
soup = BeautifulSoup(page, 'html.parser')
Then you can very well verify if it parsed properly
print(soup.prettify())
Upvotes: 0