Primero, adjunte el programa en el curso, no se puede ejecutar normalmente
Cambie la URL de 2016 por la URL de este año: http://www.shanghairanking.cn/rankings/bcur/2020
el código se muestra a continuación:
import requests
from bs4 import BeautifulSoup
import bs4
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def fillUnivList(ulist, html):
soup = BeautifulSoup(html, "html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
ulist.append([tds[0].string, tds[1].string, tds[3].string])
def printUnivList(ulist, num):
print("{:^10}\t{:^6}\t{:^10}".format("排名","学校名称","总分"))
for i in range(num):
u=ulist[i]
print("{:^10}\t{:^6}\t{:^10}".format(u[0],u[1],u[2]))
def main():
uinfo = []
url = 'http://www.shanghairanking.cn/rankings/bcur/2020'
html = getHTMLText(url)
fillUnivList(uinfo, html)
printUnivList(uinfo, 20) # 20 univs
main()
Resultado de salida:
报错
AttributeError: el objeto 'NoneType' no tiene atributo 'children'
Encuentra la causa del problema
Primero genere el contenido del sitio web, el código es el siguiente:
from bs4 import BeautifulSoup
import requests
r = requests.get('https://www.shanghairanking.cn/rankings/bcur/2020')
r.encoding = r.apparent_encoding
demo = r.text
soup = BeautifulSoup(demo,'html.parser')
print(soup.prettify())
Parte del resultado:
En el resultado de salida, puede ver que la etiqueta tbody contiene la información de todas las universidades, la etiqueta tr contiene toda la información de una universidad y la etiqueta td contiene cada información de una sola universidad. Pero la diferencia con el material didáctico de Songtian es que la etiqueta que contiene el nombre de la universidad es la etiqueta a debajo de td.
Entonces, el problema debería ser parte de obtener el nombre de la universidad.
Imprima el contenido de la lista impresa.
el código se muestra a continuación:
La declaración:
ulist.append([tds[0].string, tds[1].string, tds[4].string])
A:
ulist.append([tds[0].string, tds[1], tds[4].string])
def fillUnivList(ulist, html):
soup = BeautifulSoup(html, "html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
ulist.append([tds[0].string, tds[1], tds[4].string])
print(ulist)
Resultado de salida:
Puede ver que el contenido que queremos está impreso, pero hay algo que no queremos.
Puede ver que el contenido que queremos está bajo la etiqueta a, y podemos usar el método .find () para recuperar el contenido que queremos.
el código se muestra a continuación:
for a in tr.find('a'):
print('a')
La salida es:
Esto es exactamente lo que queremos y lo asignamos a tds.
el código se muestra a continuación:
def fillUnivList(ulist, html):
soup = BeautifulSoup(html, "html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
# ulist.append([tds[0].string, tds[1], tds[4].string])
for a in tr.find('a'):
# print(a)
ulist.append([tds[0].string, a, tds[4].string])
La salida es:
El contenido es exactamente lo que queremos, pero el diseño no es lo suficientemente ordenado. La razón es que el contenido de ulist contiene saltos de línea.
Reemplace el carácter de nueva línea en ulist con el método .replace (), y no habrá problema de nueva línea.
el código se muestra a continuación:
def printUnivList(ulist, num):
print("{:^10}\t{:^6}\t{:^10}".format("排名","学校名称","总分"))
for i in range(num):
u=ulist[i]
print("{:^10}\t{:^6}\t{:^10}".format(u[0].replace('\n',''), u[1].replace('\n',''), u[2].replace('\n','')))
Resultado de salida:
Esta es exactamente la composición tipográfica y el contenido que queremos. Modifique el formato impreso por print () para obtener una composición tipográfica más ordenada.
El código general del programa es el siguiente:
import requests
from bs4 import BeautifulSoup
import bs4
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def fillUnivList(ulist, html):
soup = BeautifulSoup(html, "html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
# ulist.append([tds[0].string, tds[1], tds[4].string])
for a in tr.find('a'):
# print(a)
ulist.append([tds[0].string, a, tds[4].string])
def printUnivList(ulist, num):
print(" {:^10}\t{:^6}\t {:^10}".format("排名","学校名称","总分"))
for i in range(num):
u=ulist[i]
print("{:^10}\t{:^6}\t{:^10}".format(u[0].replace('\n',''), u[1].replace('\n',''), u[2].replace('\n','')))
def main():
uinfo = []
url = 'http://www.shanghairanking.cn/rankings/bcur/2020'
html = getHTMLText(url)
fillUnivList(uinfo, html)
printUnivList(uinfo, 20) # 20 univs
main()