繁体   English   中英

美汤单题多选

[英]Beautiful Soup Multiple Answers from Single Question

我正在尝试使用 Beautiful Soup 抓取一个有多个答案的 html 测验。 我能够独立地抓取答案和问题,并且已经找到了如何组合其中一些的方法,错误如下。 问题是有些问题的答案不止一个,所以我在输出上相差一个,即问题 1 有多个答案只会有一个,然后问题 2 会有问题 1 的答案。 html 代码中有很多层,即复选框、正确的标签和不正确的标签答案……这对下一个问题以相同的顺序重复。 最终状态是抓取正确的问题和答案,然后将它们转储到闪存卡程序中以供学习之用。 我不确定这是否是最好的方法,或者是否有另一个可以更好地工作的 python 库? 任何方向和帮助将不胜感激。

问题 1 HTML:

<div class="detailed-result-panel--panel-row--2aE8z detailed-result-panel--question-container--7NyiS">
   <form class="">
    <div class="mc-quiz-question--header--3fsHJ">
     <span>
      Question 1:
     </span>
     <span class="mc-quiz-question--incorrect--1QOBY">
      Incorrect
     </span>
     <div class="mc-quiz-question--question-prompt--2_dlz" data-purpose="safely-set-inner-html:rich-text-viewer:html" id="question-prompt">
      <p>
       Select TWO examples of XYZ.
      </p>
     </div>
    </div>
    <ul aria-labelledby="question-prompt" role="group">
     <li>
      <div class="mc-quiz-answer--answer-body--1JtTQ mc-quiz-answer--incorrect--2v11K checkbox boxed disabled">
       <label title="">
        <div class="pos-r">
         <input checked="" data-index="0" disabled="" name="answer" type="checkbox"/>
         <span class="toggle-control-label checkbox-label">
 </span>
        </div>
        <div class="fx toggle-control-label">
         <div class="fx fx-lc mc-quiz-answer--incorrect--2v11K">
          <div class="fx">
           <div class="mc-quiz-answer--question-copy--314BC" data-purpose="safely-set-inner-html:rich-text-viewer:html">
            <p>
             ANSWER 1
            </p>
           </div>
          </div>
          <div class="mc-quiz-answer--correctness--3pFQG">
           (Incorrect)
          </div>
         </div>
        </div>
       </label>
      </div>
     </li>
     <li>
      <div class="mc-quiz-answer--answer-body--1JtTQ checkbox boxed disabled">
       <label title="">
        <div class="pos-r">
         <input data-index="1" disabled="" name="answer" type="checkbox"/>
         <span class="toggle-control-label checkbox-label">          ​
         </span>
        </div>
        <div class="fx toggle-control-label">
         <div class="fx fx-lc">
          <div class="fx">
           <div class="mc-quiz-answer--question-copy--314BC" data-purpose="safely-set-inner-html:rich-text-viewer:html">
            <p>
             ANSWER 2
            </p>
           </div>
          </div>
         </div>
        </div>
       </label>
      </div>
     </li>
     <li>
      <div class="mc-quiz-answer--answer-body--1JtTQ mc-quiz-answer--correct--is6Db checkbox boxed disabled">
       <label title="">
        <div class="pos-r">
         <input checked="" data-index="2" disabled="" name="answer" type="checkbox"/>
         <span class="toggle-control-label checkbox-label">          ​
         </span>
        </div>
        <div class="fx toggle-control-label">
         <div class="fx fx-lc mc-quiz-answer--correct--is6Db">
          <div class="fx">
           <div class="mc-quiz-answer--question-copy--314BC" data-purpose="safely-set-inner-html:rich-text-viewer:html">
            <p>
             ANSWER 3
            </p>
           </div>
          </div>
          <div class="mc-quiz-answer--correctness--3pFQG">
           (Correct)
          </div>
         </div>
        </div>
       </label>
      </div>
     </li>
     <li>
      <div class="mc-quiz-answer--answer-body--1JtTQ mc-quiz-answer--correct--is6Db checkbox boxed disabled">
       <label title="">
        <div class="pos-r">
         <input data-index="3" disabled="" name="answer" type="checkbox"/>
         <span class="toggle-control-label checkbox-label">          ​
         </span>
        </div>
        <div class="fx toggle-control-label">
         <div class="fx fx-lc mc-quiz-answer--correct--is6Db">
          <div class="fx">
           <div class="mc-quiz-answer--question-copy--314BC" data-purpose="safely-set-inner-html:rich-text-viewer:html">
            <p>
             XYZ Management
            </p>
           </div>
          </div>
          <div class="mc-quiz-answer--correctness--3pFQG">
           (Correct)
          </div>
         </div>
        </div>
       </label>
      </div>
     </li>
     <li>
      <div class="mc-quiz-answer--answer-body--1JtTQ checkbox boxed disabled">
       <label title="">
        <div class="pos-r">
         <input data-index="4" disabled="" name="answer" type="checkbox"/>
         <span class="toggle-control-label checkbox-label">          
         </span>
        </div>
        <div class="fx toggle-control-label">
         <div class="fx fx-lc">
          <div class="fx">
           <div class="mc-quiz-answer--question-copy--314BC" data-purpose="safely-set-inner-html:rich-text-viewer:html">
            <p>
             ANSWER 4 
            </p>
           </div>
          </div>
         </div>
        </div>
       </label>
      </div>
     </li>
    </ul>

代码:

from bs4 import BeautifulSoup
import re

with open('inputfile.html', encoding="utf-8") as f:
    contents = f.read()
    soup = BeautifulSoup(contents, 'lxml')

questions = soup.find_all('div','mc-quiz-question--question-prompt--2_dlz')

answers = soup.find_all('div','fx fx-lc mc-quiz-answer--correct--is6Db', 'safely-set-inner-html:rich-text-viewer:html')

for q, a in zip(questions, answers):
    print(' '.join((q.p.text, a.p.text)))

我的输出:

Select TWO examples of XYZ. ANSWER 3 
What does XYZ provide? ANSWER 4 <--- this is from the previous Question 

预期输出:

Question: Select TWO examples of XYZ. 
Answer: ANSWER 3 ANSWER 4 
Question: What does XYZ provide? 
Answer: ANSWER 1
Question: How does XYZ do ABC? 
Answer: ANSWER 3

错误

这将解析大约一半然后错误,假设它期望文本类型并返回其他内容。

Traceback (most recent call last):
  File "myparsar.py", line 111, in <module>
    print(' '.join((q.p.text, a.p.text)))
AttributeError: 'NoneType' object has no attribute 'text'

好的,如果我理解正确,您想从一个问题中提取多个更正的答案。 你大部分都做对了。 但是在 for 循环中,您错误地使用了 zip 函数。 我建议你在这里检查一下

如果您有多个问题,您应该开始通过其容器查找所有问题:

question_containers = soup.find_all('div', 'detailed-result-panel--question-container--7NyiS')

然后您可以遍历每个容器以获取问题和答案。

for container in question_containers:
    question = container.find('div', 'mc-quiz-question--question-prompt--2_dlz')
    answers = container.find_all('div', 'fx fx-lc mc-quiz-answer--correct--is6Db', 'safely-set-inner-html:rich-text-viewer:html')

由于您对一个问题有多个答案,因此您应该使用嵌套的 for 循环来遍历所有答案:

ans = []
for a in answers:
    answer_text = a.text.strip().split('\n')
    ans.append(answer_text[0])
print('Question:\n', question.text.strip(), '\nAnswers:\n', ', '.join(ans))

对于每个答案,我使用 .text、.strip 和 .split 来仅获取答案文本。 然后我将其附加到答案列表中,并使用此列表打印出您想要的内容。

完整代码:

soup = BeautifulSoup(contents, 'lxml')

question_containers = soup.find_all('div', 'detailed-result-panel--question-container--7NyiS')
for container in question_containers:
    question = container.find('div', 'mc-quiz-question--question-prompt--2_dlz')
    answers = container.find_all('div', 'fx fx-lc mc-quiz-answer--correct--is6Db', 'safely-set-inner-html:rich-text-viewer:html')

    ans = []
    for a in answers:
        answer_text = a.text.strip().split('\n')
        ans.append(answer_text[0])
    print('Question:\n', question.text.strip(), '\nAnswers:\n', ', '.join(ans))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM