BeautifulSoup:从表单中删除答案

时间:2017-08-06 14:11:10

标签: python selenium web-scraping beautifulsoup

我需要从以下link中搜索问题的答案,包括复选框。

这是我到目前为止所拥有的:

from bs4 import BeautifulSoup
import selenium.webdriver as webdriver

url = 'https://www.adviserinfo.sec.gov/IAPD/content/viewform/adv/Sections/iapd_AdvPrivateFundReportingSection.aspx?ORG_PK=161227&FLNG_PK=05C43A1A0008018C026407B10062D49D056C8CC0'

driver = webdriver.Firefox()
driver.get(url)

soup = BeautifulSoup(driver.page_source)

以下给出了所有书面答案,如果有的话:

soup.find_all('span', {'class':'PrintHistRed'})

我认为我可以将所有复选框答案拼凑在一起:

soup.find_all('img')

但这些都没有正确订购,因为这并没有获得“没有信息”和“#34;"答案不是用红色写的。

我也觉得有更好的方法可以做到这一点。理想情况下,我希望(前6个问题)返回:

['APEX INVESTMENT FUND, V, L.P',
 '805-2054766781',
 'Delaware',
 'United States',
 'APEX MANAGEMENT V, LLC',
 'X',
 'O',
 'No Information Filed',
 'NO',
 'NO']

修改

马丁在下面的回答似乎可以解决问题,但是当我把它放在循环中时,结果在第3次迭代后开始改变。任何想法如何解决这个问题?

from bs4 import BeautifulSoup
import requests
import re

for x in range(5):
    url = 'https://www.adviserinfo.sec.gov/IAPD/content/viewform/adv/Sections/iapd_AdvPrivateFundReportingSection.aspx?ORG_PK=161227&FLNG_PK=05C43A1A0008018C026407B10062D49D056C8CC0'
    html = requests.get(url)
    soup = BeautifulSoup(html.text, "lxml")

    tags = list(soup.find_all('span', {'class':'PrintHistRed'}))
    tags.extend(list(soup.find_all('img', alt=re.compile('Radio|Checkbox')))[2:])       # 2: skip "are you an adviser" at the top
    tags.extend([t.parent for t in soup.find_all(text="No Information Filed")])

    output = []

    for entry in sorted(tags):
        if entry.name == 'img':
            alt = entry['alt']
            if 'Radio' in alt:
                output.append('NO' if 'not selected' in alt else 'YES')
            else:
                output.append('O' if 'not checked' in alt else 'X')
        else:
            output.append(entry.text)

    print output[:9] 

2 个答案:

答案 0 :(得分:1)

网站不会通过Javascript生成任何所需的HTML,因此我选择仅使用requests来获取HTML(应该更快)。

解决问题的一种方法是将三种不同类型的所有标记存储到一个数组中。如果然后对其进行排序,则将导致标记按树顺序排列。

第一次搜索只是使用您的PrintHistRed来获取匹配的范围标记。其次,它会找到包含imgalt字样的Radio文字的所有Checkbox代码。最后,它会搜索找到No Information Filed的所有位置,并返回父标记。

现在可以对标签进行排序,并构建一个包含所需格式信息的合适output数组:

from bs4 import BeautifulSoup
import requests
import re

url = 'https://www.adviserinfo.sec.gov/IAPD/content/viewform/adv/Sections/iapd_AdvPrivateFundReportingSection.aspx?ORG_PK=161227&FLNG_PK=05C43A1A0008018C026407B10062D49D056C8CC0'
html = requests.get(url)
soup = BeautifulSoup(html.text, "lxml")

tags = list(soup.find_all('span', {'class':'PrintHistRed'}))
tags.extend(list(soup.find_all('img', alt=re.compile('Radio|Checkbox')))[2:])       # 2: skip "are you an adviser" at the top
tags.extend([t.parent for t in soup.find_all(text="No Information Filed")])

output = []

for entry in sorted(tags):
    if entry.name == 'img':
        alt = entry['alt']
        if 'Radio' in alt:
            output.append('NO' if 'not selected' in alt else 'YES')
        else:
            output.append('O' if 'not checked' in alt else 'X')
    else:
        output.append(entry.text)

print output[:9]        # Display the first 9 entries

给你:

[u'APEX INVESTMENT FUND V, L.P.', u'805-2054766781', u'Delaware', u'United States', 'X', 'O', u'No Information Filed', 'NO', 'YES']

答案 1 :(得分:0)

我仔细看了一下HTML。我怀疑是否有一种非常简单的方法来抓取这样的页面。

我会从分析开始,寻找类似的问题。例如,11到16(包括11和16)可能以相同的方式处理。 19和21似乎相似。可能有也可能没有。

我会弄清楚如何处理包含它们的行给出的每种类型的类似问题。例如,我如何处理19和21?然后我会编写代码来识别问题的行,并注明每个问题的编号。最后,我将使用相应的代码使用行号来从中获取信息。换句话说,当我遇到问题19时,我会使用19或21的代码。