Страницы

Поиск по вопросам

Показаны сообщения с ярлыком lxml. Показать все сообщения
Показаны сообщения с ярлыком lxml. Показать все сообщения

понедельник, 30 марта 2020 г.

Аналог innerHTML для lxml

#html #python #lxml


Как получить всё содержимое внутри HTML-тега в lxml, но без самого тега?
    


Ответы

Ответ 1



Встроенного метода вроде бы нет, но нетрудно написать свой. Проблема в том, что простой текст в lxml не является самостоятельным элементом (в отличие от Text Node в браузерах), поэтому нужно не забыть добавить text в начале. from html import escape # Доступно с Python 3.2 import lxml.html def inner_html(elem): # Текст в самом начале внутри тега # (не забываем про экранирование!) result = [escape(elem.text or '')] # Все элементы-потомки for child in elem.iterchildren(): result.append(lxml.html.tostring(child, encoding='unicode')) # Текст в конце тега принадлежит последнему элементу-потомку (tail) # и добавится автоматически # Собираем результат в одну строку return ''.join(result) # В примере подставим <br> чтобы проверить экранирование >>> node = lxml.html.fragment_fromstring( '
Тек<br>ст1

Тек<br>ст2

Текст3
Текст4
' ) >>> lxml.html.tostring(node, encoding='unicode') '
Тек<br>ст1

Тек<br>ст2

Текст3
Текст4
' >>> inner_html(node) 'Тек<br>ст1

Тек<br>ст2

Текст3
Текст4'

вторник, 25 февраля 2020 г.

Как распарсить нетривиальный XML на питоне?

#python #xml #lxml



    
        
            
                
                    
                    
                        ${host}
                        ${port}
                    
                    
                
                
                    
                    
                        220
                    
                    220 localhost SMTP
Server (JAMES SMTP Server 2.3.2)(MSK)
                    
                
                
                    
                    
                        name
                    
                    
                
                
                    
                    
                        250
                    
                    250 localhost
Hello name (localhost [127.0.0.1])
                    
            
            Test "g_helo_with_C_OrJoin273_" in keyword-driven format.
            
            
        
        
            
                
                    
                    
                        ${host}
                        ${port}
                    
                    
                
                
                    
                    
                        220
                    
                    220 localhost SMTP Server
(JAMES SMTP Server 2.3.2) 14:50:18 +0400 (MSK)
                    
                
                
                    
                    
                        name
                    
                    
                
                
                    
                    
                        255
                    
                    250 localhost
Hello name (localhost [127.0.0.1])
                    
                
            
            Test "g_helo_with_C_OrJoin273_helo_resp_2_2_trace0001_L" in keyword-driven
format.
            
            
        
    
    



Как распарсить так, чтоб в выводе было: suite source и соответствующие ему kw name,
arguments, status?
Проблема в том, что я не знаю как выводить список suite source, а в нем еще список
kw name, arguments, status.
    


Ответы

Ответ 1



Вам поможет minidom: from xml.dom import minidom om = minidom.parseString(x) root = om.getElementsByTagName('robot')[0] # Далее что-то, к примеру: def walk(x, d=0): print(' ' * d + str(x)) if x.attributes is not None: for i, j in x.attributes.items(): print(' ' * d + ' | ' + i + ': ' + j) for i in x.childNodes: walk(i, d+1) walk(root)

Ответ 2



Для сравнения, код на основе xml.etree.ElementTree: #!/usr/bin/env python import xml.etree.ElementTree as etree robot = etree.parse('input.xml').getroot() for suite in robot.iter('suite'): print("suite " + suite.get('source')) for kw in suite.findall('./test/kw'): print("\tkw" + kw.get('name')) for arg in kw.find('arguments') or []: print("\t\targ " + arg.text) print("\t\t" + "\n\t\t".join(map("=".join, sorted(kw.find('status').items())))) Output suite /home/Robot suite /home/Join273_helo_resp_2_1_trace0001_L.txt kwSmtpLibrary.Connect To Smtp arg ${host} arg ${port} endtime=20150623 14:50:18.241 starttime=20150623 14:50:18.234 status=PASS kwSmtpLibrary.Check Response arg 220 endtime=20150623 14:50:18.257 starttime=20150623 14:50:18.241 status=PASS ... suite /home/_2_2_trace0001_L.txt kwSmtpLibrary.Connect To Smtp arg ${host} arg ${port} endtime=20150623 14:50:18.275 starttime=20150623 14:50:18.274 status=PASS kwSmtpLibrary.Check Response arg 220 endtime=14:50:18.277 starttime=20150623 14:50:18.275 status=PASS ...

пятница, 24 января 2020 г.

UnicodeDecodeError: 'utf-8' codec can't decode byte, Python

#python #utf_8 #lxml


Учусь потихоньку парсить, возникла проблема с кодировкой. Код работает, но на некоторых
страницах выкидывает ошибку UnicodeDecodeError: 'utf-8' codec can't decode byte 0xae
in position 12: invalid start byte
и ругается на строку  print(company.text_content())
Как я понял, данная строка не может быть интерпретирована, как текст в UTF-8. Нашел
решение такой же проблемы https://stackoverflow.com/questions/10226342/how-to-handle-unicodedecodeerror-without-losing-any-data
, но к сожалению не помогло. Может еще что-нибудь посоветуете? 

import urllib.request
import lxml.html as html
import time

BASE_URL="http://www.wholesalecentral.com/catoverview.htm"

def pars_company(url):
"""парсим компании на странице
СНачала парсим первую страницу, потом находим ссылки на все другие страницы и в цикле
парсим их, далее сохраняем все в словарь"""
    dict_company={}
    page = urllib.request.urlopen(url)
    doc = html.document_fromstring(page.read())
    for company in doc.xpath('.//div[@class="row listings"]/p/a[@onclick]'):

    print(company.text_content()) 


    dict_company[company.text_content()]=company.get('href')

    page = urllib.request.urlopen(url)
    doc = html.document_fromstring(page.read())
    pages=doc.xpath('.//div[@class="wide-content column"]/div[@class="row"]/p/a')

    for link in pages:
        next_link=urllib.request.urljoin(BASE_URL, link.get('href'))
        page = urllib.request.urlopen(next_link)
        doc = html.document_fromstring(page.read())
        for company in doc.xpath('.//div[@class="row listings"]/p/a[@onclick]'):
        dict_company[company.text_content()]=company.get('href')
    return dict_company

def main():
    #dict_link=pars_mainpage(BASE_URL)
    pars_company('http://www.wholesalecentral.com/Licensed-Items-Collectibles.html?visitorid=654393974&dbid=1')




if  __name__ ==  "__main__" :
    main()

    


Ответы

Ответ 1



В общем проблема решилась изменением одной строчки: doc = html.document_fromstring(page.read().decode(encoding='unicode-escape'))

среда, 22 января 2020 г.

Как в cssselect прописать отсутствие класса

#python #python_3x #lxml #cssselect


Добрый день. у меня возникла проблема:
допустим мне надо найти весь текст в блоке

тогда я пишу text = str_html.cssselect('div.ringtone') Но если мне надо вытащить
я не знаю что надо писать. Вариант с 'div:nth-child(num)' не подходит, так как теги с классом и теги без класса находятся на одном уровне. Заранее благодарен.


Ответы

Ответ 1



В css работает так: console.log([...document.querySelectorAll("div:not([class])")]) console.log([...document.querySelectorAll('div:not([class]), div[class=""]')])


Ответ 2



Вот что помогло - с помощью сopy selector в Chrome достал div:nth-child(8) Спасибо большое всем за ответы

пятница, 7 июня 2019 г.

Аналог innerHTML для lxml

Как получить всё содержимое внутри HTML-тега в lxml, но без самого тега?


Ответ

Встроенного метода вроде бы нет, но нетрудно написать свой.
Проблема в том, что простой текст в lxml не является самостоятельным элементом (в отличие от Text Node в браузерах), поэтому нужно не забыть добавить text в начале.
from html import escape # Доступно с Python 3.2 import lxml.html
def inner_html(elem): # Текст в самом начале внутри тега # (не забываем про экранирование!) result = [escape(elem.text or '')]
# Все элементы-потомки for child in elem.iterchildren(): result.append(lxml.html.tostring(child, encoding='unicode')) # Текст в конце тега принадлежит последнему элементу-потомку (tail) # и добавится автоматически
# Собираем результат в одну строку return ''.join(result)

# В примере подставим <br> чтобы проверить экранирование >>> node = lxml.html.fragment_fromstring( '

Тек<br>ст1

Тек<br>ст2

Текст3
Текст4
' )
>>> lxml.html.tostring(node, encoding='unicode') '
Тек<br>ст1

Тек<br>ст2

Текст3
Текст4
'
>>> inner_html(node) 'Тек<br>ст1

Тек<br>ст2

Текст3
Текст4'

понедельник, 13 мая 2019 г.

Как распарсить нетривиальный XML на питоне?

${host} ${port} 220 220 localhost SMTP Server (JAMES SMTP Server 2.3.2)(MSK) name 250 250 localhost Hello name (localhost [127.0.0.1]) Test "g_helo_with_C_OrJoin273_" in keyword-driven format. ${host} ${port} 220 220 localhost SMTP Server (JAMES SMTP Server 2.3.2) 14:50:18 +0400 (MSK) name 255 250 localhost Hello name (localhost [127.0.0.1]) Test "g_helo_with_C_OrJoin273_helo_resp_2_2_trace0001_L" in keyword-driven format.
Как распарсить так, чтоб в выводе было: suite source и соответствующие ему kw name, arguments, status? Проблема в том, что я не знаю как выводить список suite source, а в нем еще список kw name, arguments, status


Ответ

Вам поможет minidom
from xml.dom import minidom
om = minidom.parseString(x) root = om.getElementsByTagName('robot')[0]
# Далее что-то, к примеру:
def walk(x, d=0): print(' ' * d + str(x)) if x.attributes is not None: for i, j in x.attributes.items(): print(' ' * d + ' | ' + i + ': ' + j) for i in x.childNodes: walk(i, d+1)
walk(root)

вторник, 12 марта 2019 г.

Как в cssselect прописать отсутствие класса

Добрый день. у меня возникла проблема: допустим мне надо найти весь текст в блоке


тогда я пишу
text = str_html.cssselect('div.ringtone')
Но если мне надо вытащить

я не знаю что надо писать. Вариант с 'div:nth-child(num)' не подходит, так как теги с классом и теги без класса находятся на одном уровне. Заранее благодарен.


Ответ

Вот что помогло - с помощью сopy selector в Chrome достал div:nth-child(8) Спасибо большое всем за ответы