Python 美化组连接两个表(行)以生成csv文件
您好,我创建了两行。如果你去这个网站 它们有“药物名称和状态”列,当您单击药物名称时,可以找到另外四列。我喜欢按顺序组合(基于药物名称) 因此,它将是药物名称、状态、展示、可用性、估计短缺持续时间、相关信息、短缺原因(根据FDASIA)。 但目前的代码只生成第一个(药物名称、状态)。 我试过了 但我得到了AttributeError:ResultSet对象没有属性“findAll”。我得到了同样的错误Python 美化组连接两个表(行)以生成csv文件,python,python-3.x,csv,beautifulsoup,Python,Python 3.x,Csv,Beautifulsoup,您好,我创建了两行。如果你去这个网站 它们有“药物名称和状态”列,当您单击药物名称时,可以找到另外四列。我喜欢按顺序组合(基于药物名称) 因此,它将是药物名称、状态、展示、可用性、估计短缺持续时间、相关信息、短缺原因(根据FDASIA)。 但目前的代码只生成第一个(药物名称、状态)。 我试过了 但我得到了AttributeError:ResultSet对象没有属性“findAll”。我得到了同样的错误 for row in rows,rows_href: 有什么建议我该如何生成我想要的吗?你的
for row in rows,rows_href:
有什么建议我该如何生成我想要的吗?你的代码太乱了 您将获得所有行、下一个所有链接,下一个您将尝试获取所有其他信息,但这样您就无法控制要在行中加入哪些值。最大的问题是,某些行的子页面上没有数据,而您的所有数据都会向上移动一行 您应该从主页上的表中获取所有行,然后使用
for loop
分别处理每一行,以仅获取此单行的其他元素-仅读取此行的链接,仅从子页面获取此行的数据,等等,并将此行的所有数据作为子列表放置在列表中[名称、状态、链接、演示、可用性、相关、原因]
。然后,您将获得下一个工作,并且只处理下一行的数据
顺便说一句:因为子页面可能有许多行,所以我在数据中创建了许多行,它们具有相同的名称、状态,但具有不同的其他值
for row in rows_href:
如果有什么不清楚的地方,请告诉我,需要更多的解释!您可能需要用于行,在zip中链接(行,行href)
,或者您需要直接在循环中执行-追加([row,div href.findAll(“tr”))
但它需要减少混乱,并对行中的行使用:
以单独搜索每行中的链接。其他页面有许多行,因此您可能必须使用相同的名称、状态保存每行,并且需要为
循环使用额外的。这只表明您创建的代码太混乱,您应该单独工作主页上的每一行都是如此。@furas非常感谢!我还有一个问题,如果我想创建列名(药物名称、状态、演示文稿…),我该怎么做?因为目前第一个药物是列名。我想如果我这样做[0:]或者不放任何东西都不会跳过标题,但它只会给我索引错误。非常感谢!我还有一个问题,如果我想创建列名(药物名称、状态、演示文稿…),我该怎么做?因为当前第一个药物是列名。我想如果我这样做[0:]或者不放任何东西都不会跳过标题,但它只会给我索引错误。您必须跳过从HTML中获得的第一行,因为它没有数据,只有对您没有用处的表标题。如果您想在文件中添加标题,请使用answerwriter.writerow中的注释行([“名称”、“状态”、“链接”、“演示”、“可用性”、“相关”、“原因])
for row in rows_href:
[name, status, values from first row on subpage]
[name, status, values from second row on subpage]
[name, status, values from string row on subpage]
from urllib.request import urlopen
from bs4 import BeautifulSoup
import csv
html = urlopen("https://www.accessdata.fda.gov/scripts/drugshortages/default.cfm")
bsObj = BeautifulSoup(html, "lxml")
# list for all rows with all values
data = []
# get table on main page
table = bsObj.find('table', {'id': 'cont'})
# work with every row separatelly
for row in table.find_all("tr")[1:]: # use `[1:]` to skip header
# get columns only in this row
cols = row.find_all('td')
# get name and url from first column
link = cols[0].find('a', href=True)
name = link.text.strip()
url = link['href']
url = "https://www.accessdata.fda.gov/scripts/drugshortages/" + url
url = url.replace(" ", "%20").replace("®", "%C2%AE")
print('name:', name)
print('url:', url)
# get status from second column
status = cols[1].text.strip()
print('status:', status)
# subpage
html = urlopen(url)
bsObj_href = BeautifulSoup(html, "lxml")
subtable = bsObj_href.find("table")
if not subtable:
data.append([name, status, link, '', '', '', ''])
print('---')
else:
for subrows in subtable.find_all('tr')[1:]: # use `[1:]` to skip header
#print(subrows)
subcols = subrows.find_all('td')
presentation = subcols[0].text.strip()
availability = subcols[1].text.strip()
related = subcols[2].text.strip()
reason = subcols[3].text.strip()
data.append([name, status, link, presentation, availability, related, reason])
print(presentation, availability, related, reason)
print('---')
print('----------')
with open("drug_shortage.csv", 'wt', newline='') as csvfile:
writer = csv.writer(csvFile)
# write header - one row - using `writerow` without `s` at the end
#writer.writerow(['Name', 'Status', 'Link', 'Presentation', 'Availability', 'Related', 'Reason'])
# write data - many rowr - using `writerows` with `s` at the end
writer.writerows(data)
# no need to close because it use `with`