问题:使用request库和BeautifulSoup抓取福布斯排行榜,并将其按照表格形式打印出来
网址:https://www.phb123.com/renwu/fuhao/20802.html
实现:
import requests
from bs4 import BeautifulSoup
import bs4
def getText(url):
headers = {'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36'}
try:
r = requests.get(url, headers=headers, timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return 'Scrapy Failed!'
def parserText(ulist, html):
soup = BeautifulSoup(html, 'html.parser')
for tr in soup.find('tbody').children:
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
for i in range(6):
if tds[i].string is None:
continue
if tds[i].string is not None:
ulist.append(
[tds[0].string, tds[1].string, tds[2].string, tds[3].string, tds[4].string, tds[5].string])
return ulist
def printText(ulist, num=100):
tplt = '{0:<4}{1:{6}^20}{2:{6}^8}{3:{6}^4}{4:{6}^20}{5:{6}^10}'
print(tplt.format(ulist[0][0], ulist[0][1], ulist[0][2], ulist[0][3],ulist[0][4], ulist[0][5], chr(12288)))
for i in range(1,num):
u = ulist[i]
print(tplt.format(u[0], u[1], u[2], u[3], u[4], u[5], chr(12288)))
def main():
url = 'https://www.phb123.com/renwu/fuhao/20802.html'
html = getText(url)
#print(html)
uinfo = []
parserText(uinfo, html)
printText(uinfo, num=502)
main()
运行以上代码,发现打印出来的格式并不是自己想要的格式。进行多次调试之后,发现问题出现在parserText(uinfo, html)函数中,将该函数返回的列表打印出来,即可发现问题所在:
[['\r\n\t\t\t\t排名', '\r\n\t\t\t\t中文名', '\r\n\t\t\t\t财富', '\r\n\t\t\t\t年龄', '\r\n\t\t\t\t财富来源', '\r\n\t\t\t\t国家'], ['\r\n\t\t\t\t1', '\r\n\t\t\t\t杰夫·贝索斯', '\r\n\t\t\t\t1284亿美元', '\r\n\t\t\t\t54', '\r\n\t\t\t\t亚马逊', '\r\n\t\t\t\t美国'], ['\r\n\t\t\t\t2', '\r\n\t\t\t\t比尔·盖茨', '\r\n\t\t\t\t915亿美元', '\r\n\t\t\t\t62', '\r\n\t\t\t\t微软', '\r\n\t\t\t\t美国'], ['\r\n\t\t\t\t3', '\r\n\t\t\t\t沃伦·巴菲特', '\r\n\t\t\t\t879亿美元', '\r\n\t\t\t\t87', '\r\n\t\t\t\t伯克希尔哈撒韦', '\r\n\t\t\t\t美国'], ['\r\n\t\t\t\t4', '\r\n\t\t\t\t伯纳德·阿诺特及家族', '\r\n\t\t\t\t764亿美元', '\r\n\t\t\t\t69', '\r\n\t\t\t\t路威酩轩', '\r\n\t\t\t\t法国'], ...
在列表中存在一些回车、换行等符号,在使用list[i][j]方式提取出来的元素时,会将此类符号自动转义,导致格式出现错乱。
遇到这个问题,我的第一想法就是将列表元素中符号去掉,然后在拼接成新的列表,这样提取元素时就不会出现问题。将列表元素中符号去掉可使用string.strip()方法,但是如何将列表元素再拼接成原始列表形式?在这一步我尝试了很多种方式都没有成功。到这里就卡住了。
回头再看看代码,在printText()函数中有提取每一个元素打印。既然如此,我何必要将元素中的特殊符号先去掉,然后再拼接成列表,再提取呢?直接在提取的时候将符号去掉不就可以了?
因此修改printText()函数代码:
def printText(ulist, num=100):
tplt = '{0:<4}{1:{6}^20}{2:{6}^8}{3:{6}^4}{4:{6}^20}{5:{6}^10}'
print(tplt.format(ulist[0][0].strip(), ulist[0][1].strip(), ulist[0][2].strip(), ulist[0][3].strip(),\
ulist[0][4].strip(), ulist[0][5].strip(), chr(12288)))
for i in range(1,num):
u = ulist[i]
try:
print(tplt.format(u[0].strip(), u[1].strip(), u[2].strip(), u[3].strip(), u[4].strip(), u[5].strip(), chr(12288)))
except:
continue
在这里仍是使用strip()方法。
同时,在打印元素时,还使用了try…except…语句块,之所以如此,是在原始网页中,有些元素并没有值,使用’-‘表示,NoneType类型自然没有strip()方法,要使用try…except忽略这种异常,并继续执行循环。
最终实现:
从这个例子中可以学习到,在编码时,并不一定只有一条路可以走,看起来“山重水复疑无路”,但稍微转变下思维,可能就“柳暗花明又一村”了。