Красивая проблема очистки текста в массиве

#python-3.x #web-scraping #beautifulsoup

#python-3.x #веб-очистка #beautifulsoup

Вопрос:

Данные =

 <div class="dojoxGridView" id="dojox_grid__View_1" role="presentation" style="width: 1900px; height: 721px; left: 1px; top: 0px;" widgetid="dojox_grid__View_1">
       <input class="dojoxGridHiddenFocus" dojoattachpoint="hiddenFocusNode" role="presentation" type="checkbox"/>
       <input class="dojoxGridHiddenFocus" role="presentation" type="checkbox"/>
       <div class="dojoxGridScrollbox" dojoattachpoint="scrollboxNode" role="presentation" style="height: 721px;">
        <div class="dojoxGridContent" dojoattachpoint="contentNode" hidefocus="hidefocus" role="presentation" style="height: 504px; width: 1900px;">
         <div role="presentation" style="position: absolute; left: 0px; top: 0px;">
          <div aria-selected="false" class="dojoxGridRow" role="row" style="">
           <table border="0" cellpadding="0" cellspacing="0" class="dojoxGridRowTable" role="presentation" style="width: 1900px;">
            <tbody>
             <tr>
              <td class="dojoxGridCell" idx="0" role="gridcell" style="display:none;width:100px;" tabindex="-1">
               78126
              </td>
              <td class="dojoxGridCell" idx="1" role="gridcell" style="width:10%;" tabindex="-1">
               Approved Plan
              </td>
              <td class="dojoxGridCell" idx="2" role="gridcell" style="width:10%;" tabindex="-1">
               G-10
              </td>
              <td class="dojoxGridCell" idx="3" role="gridcell" style="width:40%;" tabindex="-1">
               ROOF PLAN
              </td>
             </tr>
            </tbody>
           </table>
          </div>
  

Ввод =

     source = driver.page_source
soup = BeautifulSoup(source, "lxml")
print(soup. prettify())
for article in soup.find_all('div', class_='dojoxGridContent'):
drawing_no = article.find_all('td', class_='dojoxGridCell', idx='3')
# ->need one more line to extract text
print(""drawing_no")
  

Вывод =

 <td class="dojoxGridCell" idx="3" role="gridcell" style="width:40%;" tabindex="-1">ROOF PLAN</td> ...
  

Я просто хочу извлечь «ПЛАН КРЫШИ», как я должен редактировать свой код?
Я попробовал drawing_no.text и drawing_no.value, но он сказал «нет атрибута».
Спасибо за вашу помощь!

Комментарии:

1. просто попробуйте с drawing_no.getText()

2. Выдает ошибку: «Объект результирующего набора не имеет атрибута ‘%s’. Вероятно, вы обрабатываете список элементов как один элемент. Вы вызывали find_all(), когда хотели вызвать find()?» Ошибка % key AttributeError: объект ResultSet не имеет атрибута ‘getText’. Вероятно, вы обрабатываете список элементов как один элемент. Вы вызывали find_all(), когда хотели вызвать find()?

3. для find_all достаточно просто добавить еще один цикл for после или, если только один элемент, заменить find_all на find

4. отредактированный drawing_no = article.find(‘td’, class_=’dojoxGridCell’, idx=’3′) . это выдает:ошибка атрибута: объект ‘NoneType’ не имеет атрибута ‘getText’

Ответ №1:

попробуйте следующий код

 source="""<div class="dojoxGridView" id="dojox_grid__View_1" role="presentation" style="width: 1900px; height: 721px; left: 1px; top: 0px;" widgetid="dojox_grid__View_1">
       <input class="dojoxGridHiddenFocus" dojoattachpoint="hiddenFocusNode" role="presentation" type="checkbox"/>
       <input class="dojoxGridHiddenFocus" role="presentation" type="checkbox"/>
       <div class="dojoxGridScrollbox" dojoattachpoint="scrollboxNode" role="presentation" style="height: 721px;">
        <div class="dojoxGridContent" dojoattachpoint="contentNode" hidefocus="hidefocus" role="presentation" style="height: 504px; width: 1900px;">
         <div role="presentation" style="position: absolute; left: 0px; top: 0px;">
          <div aria-selected="false" class="dojoxGridRow" role="row" style="">
           <table border="0" cellpadding="0" cellspacing="0" class="dojoxGridRowTable" role="presentation" style="width: 1900px;">
            <tbody>
             <tr>
              <td class="dojoxGridCell" idx="0" role="gridcell" style="display:none;width:100px;" tabindex="-1">
               78126
              </td>
              <td class="dojoxGridCell" idx="1" role="gridcell" style="width:10%;" tabindex="-1">
               Approved Plan
              </td>
              <td class="dojoxGridCell" idx="2" role="gridcell" style="width:10%;" tabindex="-1">
               G-10
              </td>
              <td class="dojoxGridCell" idx="3" role="gridcell" style="width:40%;" tabindex="-1">
               ROOF PLAN
              </td>
             </tr>
            </tbody>
           </table>
          </div>"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(source,"html.parser")
for article in soup.find_all('div', class_='dojoxGridContent'):
  drawing_no = article.find('td', class_='dojoxGridCell', idx='3')
  if drawing_no:
    print(drawing_no.get_text())
  

Комментарии:

1. Ошибка: ошибка атрибута: объект ‘NoneType’ не имеет атрибута ‘get_text’

2. возможно, если убедиться, что в некоторых статьях нет элемента таблицы с соответствующим td, проверьте обновлено, и оно печатает только, если элемент существует

3. та же ошибка: ( «Объект результирующего набора не имеет атрибута ‘%s’. Вероятно, вы обрабатываете список элементов как один элемент. Вы вызывали find_all(), когда хотели вызвать find()?» Ошибка % key AttributeError: объект ResultSet не имеет атрибута ‘get_text’. Вероятно, вы обрабатываете список элементов как один элемент. Вы вызывали find_all(), когда хотели вызвать find()?

4. вы обратили внимание на статью. найти изменение я заменил find_all

5. о нет, я этого не делал, это работает! выдает: ПЛАН КРЫШИ, но как мне получить все элементы?

Ответ №2:

пожалуйста, попробуйте приведенный ниже код. Но в целом, если вы передадите idx= 3, это вернет только один элемент. Если вы хотите извлечь текст из нескольких элементов, вы можете захотеть использовать более общий идентификатор.

 import lxml
from lxml import html

html_string = """
<div class="dojoxGridView" id="dojox_grid__View_1" role="presentation" style="width: 1900px; height: 721px; left: 1px; top: 0px;" widgetid="dojox_grid__View_1">
  <input class="dojoxGridHiddenFocus" dojoattachpoint="hiddenFocusNode" role="presentation" type="checkbox"/>
  <input class="dojoxGridHiddenFocus" role="presentation" type="checkbox"/>
  <div class="dojoxGridScrollbox" dojoattachpoint="scrollboxNode" role="presentation" style="height: 721px;">
    <div class="dojoxGridContent" dojoattachpoint="contentNode" hidefocus="hidefocus" role="presentation" style="height: 504px; width: 1900px;">
      <div role="presentation" style="position: absolute; left: 0px; top: 0px;">
        <div aria-selected="false" class="dojoxGridRow" role="row" style="">
          <table border="0" cellpadding="0" cellspacing="0" class="dojoxGridRowTable" role="presentation" style="width: 1900px;">
            <tbody>
              <tr>
                <td class="dojoxGridCell" idx="0" role="gridcell" style="display:none;width:100px;" tabindex="-1">
                78126
                </td>
                <td class="dojoxGridCell" idx="1" role="gridcell" style="width:10%;" tabindex="-1">
                Approved Plan
                </td>
                <td class="dojoxGridCell" idx="2" role="gridcell" style="width:10%;" tabindex="-1">
                G-10
                </td>
                <td class="dojoxGridCell" idx="3" role="gridcell" style="width:40%;" tabindex="-1">
                ROOF PLAN
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </div>
</div>
"""

tree = html.fromstring(html_string)
ROOFPLAN = tree.xpath('//tbody/tr//td[@idx="3"]/text()')
print(''.join(ROOFPLAN).strip())
  

Комментарии:

1. Ошибка типа: ожидаемый объект, подобный строке или байтам

2. поддержано, кстати, в отличие от bs4, в нем нет «,’ между строками, могу ли я экспортировать его в csv или pandas? это дает что-то вроде ROOF PLANLOWER GROUND FL. PLANGROUND FL. ПЛАНИРУЕМ 1-Й этап. ПЛАНИРУЕМ 2-Й этап. ПЛАН 3RD FL. ПЛАНИРУЮ 14-Й FL. ПЛАН И 16-й этап. ПЛАНИРУЮ НА 18-Й ЭТ. ПЛАНИРУЙТЕ 15-Й ЭТАП ЛИКВИДАЦИИ ПОСЛЕДСТВИЙ ПОЖАРА.19-й этап. ПЛАНИРУЕМ 20-Й FL. ПЛАНИРУЮ К 25-МУ FL. РАСЧЕТ ПЛАНА ВЫЧИСЛЕНИЯ ОБЛАСТИ ЗАТЕНЕНИЯ, СЕКЦИЯ A — СЕКЦИЯ B — СЕВЕРО-ЗАПАДНАЯ ВЫСОТА, СЕВЕРО-ВОСТОЧНАЯ ВЫСОТА, ЮГО-ВОСТОЧНАЯ ВЫСОТА, без пробелов

3. было бы более понятно, если бы вы могли поделиться исходным кодом, поскольку я не знаю из приведенного выше, где хранится текст

Ответ №3:

Вы можете использовать idx атрибут и выбирать по его значению

 print(soup.select_one("[idx='3']").text.strip())