如何解决抓取表python时bs4属性错误
我正在尝试使用 bs4 刮一张桌子。但是每当我遍历 <tbody>
元素时,都会出现以下错误:Traceback (most recent call last): File "f:\Python Programs\COVID-19 Notifier\main.py",line 28,in <module> for tr in soup.find('tbody').findAll('tr'): AttributeError: 'nonetype' object has no attribute 'findAll'
我是 bs4 的新手,以前也多次遇到过这个错误。这是我正在使用的代码。任何帮助将不胜感激,因为这是一个要在比赛中提交的官方项目,截止日期临近。提前致谢。以及 beautifulsoup4=4.8.2
、bs4==0.0.4
和 soupsieve==2.0
。
我的代码:
from plyer import notification
import requests
from bs4 import BeautifulSoup
import time
def notifyMe(title,message):
notification.notify(
title = title,message = message,app_icon = ".\\icon.ico",timeout = 6
)
def getData(url):
r = requests.get(url)
return r.text
if __name__ == "__main__":
while True:
# notifyMe("Harry","Lets stop the spread of this virus together")
myHtmlData = getData('https://www.mohfw.gov.in/')
soup = BeautifulSoup(myHtmlData,'html.parser')
#print(soup.prettify())
myDataStr = ""
for tr in soup.find('tbody').find_all('tr'):
myDataStr += tr.get_text()
myDataStr = myDataStr[1:]
itemList = myDataStr.split("\n\n")
print(itemList)
states = ['Chandigarh','Telengana','Uttar Pradesh']
for item in itemList[0:22]:
dataList = item.split('\n')
if dataList[1] in states:
nTitle = 'Cases of Covid-19'
nText = f"State {dataList[1]}\nIndian : {dataList[2]} & Foreign : {dataList[3]}\nCured : {dataList[4]}\nDeaths : {dataList[5]}"
notifyMe(nTitle,nText)
time.sleep(2)
time.sleep(3600)
解决方法
这一行引发了错误:
for tr in soup.findAll('tbody').findAll('tr'):
您只能在单个标签上调用 find_all
,不能在另一个 find_all
返回的结果集上调用。 (findAll
与 find_all
相同 - 最好使用后者,因为它符合 Python PEP 8 styling standard)
find_all() 方法查看标签的后代并检索与您的过滤器匹配的所有后代。
如果您要遍历单个表,只需将第一个 findAll
替换为 find
。如果有多个表,将结果集存储在一个变量中并循环遍历它,您可以将 findAll
应用于单个标签。
这应该可以解决它:
for tr in soup.find('tbody').find_all('tr'):
多个表:
tables = soup.find_all('tbody')
for table in tables:
for tr in table.find_all('tr'):
...
,
这里有几个问题。
-
<tbody>
标签位于 html 的注释中。 BeautifulSoup 会跳过评论,除非您专门提取评论。 - 为什么要使用
getData()
函数?这只是一行,为什么不把它放到代码中。额外的函数并没有真正提高代码的效率或可读性。 - 即使您拉动 tbody> 标签,您的 dataList 也没有 6 个项目(您调用 dataList[5],这会抛出并出错)。我调整了它,但我不知道这些是否是正确的数字。我不知道每个 vlaues 代表什么,所以你可能需要解决这个问题。您要提取的数据的标头是
['S. No.','Name of State / UT','Active Cases*','Cured/Discharged/Migrated*','Deaths**']
,所以我不知道Indian : {dataList[2]} & Foreign :
应该是什么。 - 这样,我不知道这些数字代表什么,但它是正确的数据吗?看起来您可以提取新数据 here,但它与
<tbody>
中的数字不同
所以,这里是为了获取其他数据源...也许它更准确?
import requests
import pandas as pd
jsonData = requests.get('https://www.mohfw.gov.in/data/datanew.json').json()
df = pd.DataFrame(jsonData)
输出:
print(df.to_string())
sno state_name active positive cured death new_active new_positive new_cured new_death state_code
0 2 Andaman and Nicobar Islands 153 5527 5309 65 146 5569 5358 65 35
1 1 Andhra Pradesh 66944 997462 922977 7541 74231 1009228 927418 7579 28
2 3 Arunachal Pradesh 380 17296 16860 56 453 17430 16921 56 12
3 4 Assam 11918 231069 217991 1160 13942 233453 218339 1172 18
4 5 Bihar 69869 365770 293945 1956 76420 378442 300012 2010 10
5 6 Chandigarh 4273 36404 31704 427 4622 37232 32180 430 04
6 7 Chhattisgarh 121555 605568 477339 6674 123479 622965 492593 6893 22
7 8 Dadra and Nagar Haveli and Daman and Diu 1668 5910 4238 4 1785 6142 4353 4 26
8 10 Delhi 91618 956348 851537 13193 92029 980679 875109 13541 07
9 11 Goa 10228 72224 61032 964 11040 73644 61628 976 30
10 12 Gujarat 92084 453836 355875 5877 100128 467640 361493 6019 24
11 13 Haryana 58597 390989 328809 3583 64057 402843 335143 3643 06
12 14 Himachal Pradesh 11859 82876 69763 1254 12246 84065 70539 1280 02
13 15 Jammu and Kashmir 16094 154407 136221 2092 16993 156344 137240 2111 01
14 16 Jharkhand 40942 184951 142294 1715 43415 190692 145499 1778 20
15 17 Karnataka 196255 1247997 1037857 13885 214330 1274959 1046554 14075 29
16 18 Kerala 156554 1322054 1160472 5028 179311 1350501 1166135 5055 32
17 19 Ladakh 2041 12937 10761 135 2034 13089 10920 135 37
18 20 Lakshadweep 803 1671 867 1 920 1805 884 1 31
19 21 Madhya Pradesh 84957 459195 369375 4863 87640 472785 380208 4937 23
20 22 Maharashtra 701614 4094840 3330747 62479 693632 4161676 3404792 63252 27
21 23 Manipur 513 30047 29153 381 590 30151 29180 381 14
22 24 Meghalaya 1133 15488 14198 157 1238 15631 14236 157 17
23 25 Mizoram 608 5220 4600 12 644 5283 4627 12 15
24 26 Nagaland 384 12800 12322 94 457 12889 12338 94 13
25 27 Odisha 32963 388479 353551 1965 36718 394694 356003 1973 21
26 28 Puducherry 5923 50580 43931 726 6330 51372 44314 728 34
27 29 Punjab 40584 319719 270946 8189 43943 326447 274240 8264 03
28 30 Rajasthan 107157 467875 357329 3389 117294 483273 362526 3453 08
29 31 Sikkim 640 6970 6193 137 693 7037 6207 137 11
30 32 Tamil Nadu 89428 1037711 934966 13317 95048 1051487 943044 13395 33
31 34 Telengana 52726 379494 324840 1928 58148 387106 326997 1961 36
32 33 Tripura 563 34302 33345 394 645 34429 33390 394 16
33 35 Uttarakhand 26980 138010 109058 1972 29949 142349 110379 2021 05
34 36 Uttar Pradesh 259810 976765 706414 10541 273653 1013370 728980 10737 09
35 37 West Bengal 68798 700904 621340 10766 74737 713780 628218 10825 19
36 11111 2428616 16263695 13648159 186920 2552940 16610481 13867997 189544
这是您提取注释的代码
代码:
import requests
from bs4 import BeautifulSoup,Comment
import time
def notifyMe(title,message):
notification.notify(
title = title,message = message,app_icon = ".\\icon.ico",timeout = 6
)
if __name__ == "__main__":
while True:
# notifyMe("Harry","Lets stop the spread of this virus together")
myHtmlData = requests.get('https://www.mohfw.gov.in/').text
soup = BeautifulSoup(myHtmlData,'html.parser')
comments = soup.find_all(string=lambda text: isinstance(text,Comment))
myDataStr = ""
for each in comments:
if 'tbody' in str(each):
soup = BeautifulSoup(each,'html.parser')
for tr in soup.find('tbody').findAll('tr'):
myDataStr += tr.get_text()
myDataStr = myDataStr[1:]
itemList = myDataStr.split("\n\n")
print(itemList)
states = ['Chandigarh','Telengana','Uttar Pradesh','Meghalaya']
for item in itemList[0:22]:
w=1
dataList = item.split('\n')
if dataList[1] in states:
nTitle = 'Cases of Covid-19'
nText = f"State {dataList[1]}\nIndian : {dataList[0]} & Foreign : {dataList[2]}\nCured : {dataList[3]}\nDeaths : {dataList[4]}" #<-- I changed this
notifyMe(nTitle,nText)
time.sleep(2)
time.sleep(3600)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。