Уведомления

Группа в Telegram: @pythonsu

#1 Март 17, 2012 16:32:06

s0rg
От:
Зарегистрирован: 2011-06-05
Сообщения: 777
Репутация: +  25  -
Профиль   Отправить e-mail  

Проблема с lxml

from http import cookies, client
from urllib.parse import urlencode, urlsplit, urljoin
from lxml.html import document_fromstring


class SimpleBrowser(object):
def __init__(self, headers=None, timeout=10):
self._cookies = cookies.SimpleCookie()
self._headers = headers if (headers is not None) \
else [('User-Agent', 'SimpleBrowser/0.1')]
self._headers.append(('Connection', 'close'))
self._host = None
self._conn = None
self._timeout = timeout

def __ensure_connection(self, host, scheme):
if self._host == host:
return

if self._conn is not None:
self._conn.close()

self._host = host

if scheme == 'http':
self._conn = client.HTTPConnection(host, timeout=self._timeout)
elif scheme == 'https':
self._conn = client.HTTPSConnection(host, timeout=self._timeout)
else:
raise ValueError('Unknown scheme: %s' % scheme)

def __prepare_url(self, url):
parsed = urlsplit(url, scheme='http')
host = parsed.netloc if parsed.netloc else self._host
self.__ensure_connection(host, parsed.scheme)
return '%s?%s' % (parsed.path, parsed.query)

def close(self):
if self._conn is not None:
self._conn.close()
self._conn = None
self._host = None

def add_header(self, name, value):
self._headers.append((name, value))

def add_cookie(self, name, value):
self._cookies[name] = value

def request(self, req, url, data=None):
if isinstance(data, dict):
data = urlencode(data)

loc = self.__prepare_url(url)
self._conn.putrequest(req, loc)
for header in self._headers:
self._conn.putheader(*header)
cookies = self._cookies.output(attrs=[], header='')
if cookies:
self._conn.putheader('Cookie', cookies.strip())
self._conn.endheaders(data)

resp = self._conn.getresponse()
resp_headers = dict(resp.getheaders())
resp_body = resp.read()
self._conn.close()
if 'Set-Cookie' in resp_headers:
self._cookies.load(resp_headers['Set-Cookie'])
if 'Set-Cookie2' in resp_headers:
self._cookies.load(resp_headers['Set-Cookie2'])

if resp.status == client.OK:
return (client.OK, document_fromstring(resp_body))
elif resp.status in (client.MOVED_PERMANENTLY, client.FOUND):
return self.request(req, resp_headers['Location'], data)
else:
return (resp.status, resp.reason)

def get(self, url):
return self.request('GET', url)

def post(self, url, data):
return self.request('POST', url, data)


if __name__ == '__main__':
sb = SimpleBrowser()
res, doc = sb.get('http://pogoda.yandex.ru/moscow/')
if res == client.OK:
for div in doc.cssselect("div.b-forecast__tday"):
print(div.text)
Как-то так ) Код не идеальный - я не тестировал post но для яндекса работает.

P.S. То, что первоначальный код сработал для 2.x но при этом не работал в 3.x ‘виновата’ именно версия:
http://docs.python.org/release/3.2/library/urllib.request.html
According to the letter of RFC 2616, 301 and 302 responses to POST requests must not be automatically redirected without confirmation by the user. In reality, browsers do allow automatic redirection of these responses, changing the POST to a GET, and urllib reproduces this behaviour.

Офлайн

#2 Март 17, 2012 19:29:03

bollustrado
От:
Зарегистрирован: 2012-03-16
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с lxml

Большое спасибо



Офлайн

#3 Март 17, 2012 23:18:54

s0rg
От:
Зарегистрирован: 2011-06-05
Сообщения: 777
Репутация: +  25  -
Профиль   Отправить e-mail  

Проблема с lxml

Немного причесал и выложил на github: https://github.com/s0rg/simplebrowser
Может кому понадобится.
Теперь одинаково работает и с 2.x и c 3.x ветками + наличие lxml не обязательно.

Офлайн

#4 Март 18, 2012 00:07:17

Spectral
От:
Зарегистрирован: 2010-07-13
Сообщения: 51
Репутация: +  1  -
Профиль   Отправить e-mail  

Проблема с lxml

s0rg
Немного причесал и выложил на github: https://github.com/s0rg/simplebrowser
Может кому понадобится.
Теперь одинаково работает и с 2.x и c 3.x ветками + наличие lxml не обязательно.
Обязательно пригодится!
Все нужные строки для приложения на Питоне, ползущего в Интернет :)



Офлайн

#5 Июль 30, 2012 10:47:07

SHDW
От:
Зарегистрирован: 2011-11-07
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с lxml

Опишу свою проблему:
есть python 3.2 x64, lxml-2.3.4
требуется запарсить сайт
пробовал

try:
from lxml import etree
import urllib.request as rqc
except ImportError:
print("import faled")
url = "http://www.plm-forum.ru/forum/viewforum.php?f=133"
f = rqc.urlopen(url)
data = f.read()
lt = etree.parse(data)
print("EOL")

в основном ругается
&bull
( возможно и на другие будет ругаться но первым встречается именно bull)
можно ли как-то обойти эту ошибку.
Задача стоит в том чтобы получить все ссылки href со страницы.
заранее спасибо



Офлайн

#6 Июль 30, 2012 11:02:54

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Проблема с lxml

Для HTML лучше использовать lxml.html вместо etree.

import lxml.html
...
lt = lxml.html.fromstring(data)
А если особых требований к скачиванию нет (куки, хедеры), можно даже так:
lt = lxml.html.parse("http://www.plm-forum.ru/forum/viewforum.php?f=133")

Офлайн

#7 Июль 30, 2012 13:08:09

SHDW
От:
Зарегистрирован: 2011-11-07
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Проблема с lxml

ммм… спасибо.
Просто в той же документации по lxml было написано что предпочтительней использовать xml парсер для xhml.



Офлайн

#8 Июль 30, 2012 16:14:59

odnochlen
Зарегистрирован: 2012-06-28
Сообщения: 794
Репутация: +  14  -
Профиль   Отправить e-mail  

Проблема с lxml

xhtml != html

Офлайн

#9 Июль 30, 2012 16:43:55

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Проблема с lxml

odnochlen
xhtml != html
Что интересно - по ссылке валидный XHTML 1.0 Strict! Надо будет завтра попробовать попарсить.



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version