lorien / grab Goto Github PK
View Code? Open in Web Editor NEWWeb Scraping Framework
Home Page: https://grab.readthedocs.io
License: MIT License
Web Scraping Framework
Home Page: https://grab.readthedocs.io
License: MIT License
Например /grab/spider/base.py : 123
* network_try_limit - How many times try to send request
again if network error was occuried, use 0 to disable
* network_try_limit - Limit of tries to execute some task
this is not the same as network_try_limit
network try limit limits the number of tries which
are performed automaticall in case of network timeout
of some other physical error
but task_try_limit limits the number of attempts which
are scheduled manually in the spider business logic
Возможно во второй раз должен быть "task_try_limit"? Выходит, что "network_try_limit - ...is not the same as network_try_limit" :)
Сразу же, /grab/spider/pattern.py : 39
def process_next_page(self, grab, task, xpath, resolve_base=False, **kwargs):
"""
Generate task for next page.
...
Example::
self.follow_links(grab, 'topic', '//div[@class="topic"]/a/@href')
"""
И т.д., хотя опечатки в примерах - это мелочи!
How to repeat:
Допустим есть такой цикл:
for elem in g.doc.select('//table[contains(@width, "100")]')[4].select('//td[contains(@valign, "middle")]'):
print(elem.text())
и допустим в документе есть 6 таблиц с width равным 100 и во всех есть td с valign равным middle
исходя из кода подразумевается, что я хочу получить только текст из 5(4) таблицы, но получаю из абсолютно всех т.е. код выше равен этому:
for elem in g.doc.select('//td[contains(@valign, "middle")]'):
print(elem.text())
мне кажется так не должно быть
использую последний grab отсюда.
При использовании process_links получаем ошибку:
ERROR:root:Call to deprecated function xpath_list. Use grab.doc.select() instead.
Видимо нужно переписать process_links и process_next_page через select?
Полагаю, что это строка 79 /grab/spider/pattern.py
Заменить
for url in grab.xpath_list(xpath):
на
for url in grab.doc.select(xpath).node_list():
Hello!
Trying simple example
from grab import Grab
g = Grab()
resp = g.go('http://livejournal.com/')
get error
File "/usr/local/lib/python2.7/site-packages/grab/transport/curl.py", line 328, in process_config
self.curl.setopt(pycurl.COOKIEFILE, '')
pycurl.error: (48, '')
FreeBSD 9.1 curl 7.33
How to fix this?
Ставил pycurl из инсталлятора на сайте (того самого, который на сайте лежит). Все работало, пока какой-то модуль не обновил grab и тут поперло.
https://groups.google.com/forum/#!topic/python-grab/7-jC2lOttWc
Lorien, петух ты ткнутый, ты сам проверяешь, что выкладываешь? Сука хуйло ты ебаное, чтоб у тебя яйца отвалились, хотя такому ботану как ты они и не нужны. Блядина ты ебаная, 1,5 часа на эту хуйню потратил. Гний, сука! Гний!!!
при режиме body_inmemory = False и транспорте curl происходит утечка открытых файлов.
причиной утечки является игнорирования хендла, возвращаемого функцией tempfile.mkstemp. этот хендл уже указывает на открытый файл, которой необходимо закрыть.
Code:
from grab import Grab
g = Grab
print g.tree
...error occurs: AttributeError: 'NoneType' object has no attribute 'unicode_runtime_body'
Grab falls even i want to check g.tree is None:
g.tree is None
... and error occurs anyway.
Bugged code is on the bottom of stack trace:
66 if self._lxml_tree is None:
67 body = self.response.unicode_runtime_body(
68 fix_special_entities=self.config['fix_special_entities']
69 ).strip()
You shouldn't try to call any self.response methods if it wasn't any response.
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
Traceback (most recent call last):
File "test.py", line 91, in
test_instance.run()
File "/usr/local/lib/python2.7/dist-packages/grab-0.4.13-py2.7.egg/grab/spider/base.py", line 941, in run
for result in self.transport.iterate_results():
File "/usr/local/lib/python2.7/dist-packages/grab-0.4.13-py2.7.egg/grab/spider/transport/multicurl.py", line 105, in iterate_results
grab.process_request_result()
File "/usr/local/lib/python2.7/dist-packages/grab-0.4.13-py2.7.egg/grab/base.py", line 511, in process_request_result
if len(value) > self.config['debug_post_limit']:
TypeError: object of type 'long' has no len()
File "/srv/myscript.py", line 383, in get_post_params
post_data = self.g.form_fields()
File "/srv/backend/booking/venv/local/lib/python2.7/site-packages/grab/ext/form.py", line 341, in form_fields
if fields[elem.name] is None:
KeyError: 'ChooseSavedCard'
On this piece of html code:
<input type="radio" name="ChooseSavedCard" id="RadioSelectNewCard" value="RadioSelectNewCard" data-bind="checked: isSavedCardCheckbox" checked />
Версия из pypi
Formatting for bytes isn't supported for Python 3.4, so code tail = b'; domain={}' % cookie_domain
in transport/curl.py
raises an error:
File "modules/grab/grab/ext/form.py", line 311, in submit
return self.request()
File "modules/grab/grab/base.py", line 442, in request
self.prepare_request(**kwargs)
File "modules/grab/grab/base.py", line 403, in prepare_request
self.transport.process_config(self)
File "modules/grab/grab/transport/curl.py", line 308, in process_config
self.process_cookie_options(grab, request_url)
File "modules/grab/grab/transport/curl.py", line 381, in process_cookie_options
tail = b'; domain={}' % cookie_domain
TypeError: unsupported operand type(s) for %: 'bytes' and 'str'
When I use pip3 to install grab
, the request works. But if I use branch master of grab as a submodule in my project, it fails : (
See: Adding % formatting to bytes and bytearray -- Request for Pronouncement
resp = g.go('http://google.com')
resp1 = resp.copy()
resp.select('//div')
<grab.selector.selector.SelectorList object at 0x7fed2275c808>
resp1.select('//div')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "../python3.4/site-packages/grab/document.py", line 490, in select
return XpathSelector(self.tree).select(*args, **kwargs)
File "../python3.4/site-packages/grab/document.py", line 351, in tree
if self.grab.config['content_type'] == 'xml':
AttributeError: 'NoneType' object has no attribute 'config'
possible solution
def copy(self):
return copy.deepcopy(self)
Столкнулся с необходимостью использовать select(xpath) в произвольном HTML коде. Решил воспользоваться подходом из статьи на хабре http://habrahabr.ru/post/173509/ , но оказывается, что класс Selector уже устарел (Selector class is deprecated. Please use XpathSelector class instead).
Как быть, что читать?
This exception should not be fatal, it should not stop all spider processes.
Grab should not raise exception if file specified in cookiefile options does not exist. Grab should ignore unexisting file.
Обратил внимание, что при таком коде (см. ниже) страницы скачиваются в рандомном порядке (т.е. не 1,2,3, а как им вздумается - 2,1,3 или 3,2,1 и т.д.)
С чем это может быть связано и как это исправить?
...
parse_pages = 3
class SpiderExample(Spider):
def task_generator(self):
for page_num in xrange(1,parse_pages+1):
yield Task('pages', url='http://url.com/?page='+str(page_num))
def task_pages(self, grab, task):
print task.url
...
Raise exception in following case:
@func_field
def some_func(self, sel):
pass
Should be:
@func_field()
def some_func(self, sel):
pass
ERROR:grab.spider.base:Error while processing content unencoding: invalid code lengths set
Подскажите как её отловить =(
Add description of how to control the maximal number of redirects
Получаю перодическу такую ошибку при запросах, пожет кто-то сталкивался?
pycurl 7.19.0.2
Stacktrace (последний вызов снизу):
File "api.py", line 156, in request
x = g1.go(url)
File "grab/base.py", line 356, in go
return self.request(url=url, **kwargs)
File "grab/base.py", line 433, in request
self.transport.request()
File "grab/transport/curl.py", line 389, in request
raise error.GrabNetworkError(ex.args[0], ex.args[1])
XPath for an empty element check :
content = doc.select(
u'boolean(//div[contains(@class, "b-serp-list")]/node())'
)
Trace:
File "parser.py", line 62, in go
u'boolean(//div[contains(@class, "b-serp-list")]/node())'
File "/development/env/lib/python2.7/site-packages/grab/ext/doc.py", line 15, in select
return XpathSelector(self.grab.tree).select(*args, **kwargs)
File "/development/env/lib/python2.7/site-packages/grab/selector/selector.py", line 160, in select
selector_list = self.wrap_node_list(self.process_query(query), query)
File "/development/env/lib/python2.7/site-packages/grab/selector/selector.py", line 167, in wrap_node_list
for node in nodes:
TypeError: 'bool' object is not iterable
Привет! :)
Было бы неплохо увидеть работу этой полезности на подобии РНР: http://php.net/strip_tags , чтобы можно было указывать какие теги оставить. Иными словами, чтобы не играться с regexp'ами, когда, например, нужно удалить все ссылки из текста (но оставить анкоры) и т.д.
Tested with revision 0ca7188
Steps to reproduce:
AirAlk:grab(master) $ rm /tmp/jar
AirAlk:grab(master) $ touch /tmp/jar
AirAlk:grab(master) $ python
Python 2.7.5 (default, Aug 25 2013, 00:04:04)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from grab import Grab
>>> g=Grab(cookiefile='/tmp/jar')
>>> g.go('http://google.com')
ERROR:root:Call to deprecated function dump_cookies. Use grab.cookies.save_to_file instead.
<grab.response.Response object at 0x104cddbb0>
>>> g=Grab(cookiefile='/tmp/jar')
>>> g.go('http://google.com')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "grab/base.py", line 368, in go
return self.request(url=url, **kwargs)
File "grab/base.py", line 443, in request
self.prepare_request(**kwargs)
File "grab/base.py", line 396, in prepare_request
self.transport.process_config(self)
File "grab/transport/curl.py", line 306, in process_config
self.process_cookie_options(grab, request_url)
File "grab/transport/curl.py", line 381, in process_cookie_options
encoded, tail))
TypeError: invalid arguments to setopt
>>>
Cookie jar:
AirAlk:grab(master) $ cat /tmp/jar
[{"comment": null, "domain": "#httponly_.google.com", "name": "NID", "expires": 1404847059, "value": "67=RmfhSy6-Q0Eq25G1w491QhHnloBwFp11ed7mBdz211R-uVrvYpPokHiWnz8l055HMzQm7IUfIHSVvF8J4Yk-CqRzpoprkvqtug7v0zbTraZzkA2JXjW3XGsfJFjdihCJ", "version": 0, "rfc2109": false, "discard": true, "path": "/", "port": null, "comment_url": null, "secure": false}, {"comment": null, "domain": "#httponly_.google.lv", "name": "NID", "expires": 1404847060, "value": "67=NXeekVhHigpPbN8lOSGAVG4fIcO5gDNBcyq9nnZxOE1ykS-yG3lE6_a5OpjE4O7cA5rUje_Z-_EhXUPKkFySh1DNdfQjHHak8jQ57b7-lC678o8dNgUK4qd8C4s7z-Fi", "version": 0, "rfc2109": false, "discard": true, "path": "/", "port": null, "comment_url": null, "secure": false}, {"comment": null, "domain": ".google.com", "name": "PREF", "expires": 1452107859, "value": "ID=ba40aa1f1893c6b2:FF=0:TM=1389035859:LM=1389035859:S=Ts4dRqBie77tN7M2", "version": 0, "rfc2109": false, "discard": true, "path": "/", "port": null, "comment_url": null, "secure": false}, {"comment": null, "domain": ".google.lv", "name": "PREF", "expires": 1452107860, "value": "ID=0e03b5592755082e:FF=0:TM=1389035860:LM=1389035860:S=BqshP7eebNoH0JS-", "version": 0, "rfc2109": false, "discard": true, "path": "/", "port": null, "comment_url": null, "secure": false}]
В текущей версии grab куки хранятся в виде dict вида имя=>значение.
Пожалуйста, реализуйте хранение куков, более приближенную к модели браузера, с сохранением информации о папке, домене и т.д.
{
"domain": ".github.com",
"expirationDate": 1476761637,
"hostOnly": false,
"httpOnly": false,
"name": "_ga",
"path": "/",
"secure": false,
"session": false,
"storeId": "0",
"value": "GA1.2.123456.78910",
"id": 1
}
Столкнулся с хитрым сайтом на Битриксе, который не отдает контент, если метод обработки куков отличается от браузерного (это наиболее вероятная причина, скажите механизм защиты, если кто знает :) ).
// English version
Current grab saves cookies using python dict with structure like name => value.
Please, implement cookie storage, which is alike browser model. I.e. with info about path, domain, etc.
P.S. I'v faced with complicated site based on Bitrix, which didn't gave me content if cookie handling is differs from browser's cookie-storage model (is it a real reasщт, maybe anybody may share details of this protection :) ).
Заранее спасибо / Thanks a lot
Как-то не ясно, тестов при беглом осмотре тоже не заметно
Сейчас в pypi лежит версия 0.4.12 c ошибкой.
File "/opt/realty/env/local/lib/python2.7/site-packages/grab/spider/task.py", line 186, in clone
task.url = url
NameError: global name 'url' is not defined```
В текущей версии данная ошибка исправлена
в доке есть такой блок
Работа с pycurl-дескриптором
Если вам нужно какая-либо возможность pycurl, интерфейс к которой отсутствует в Grab, вы можете работать с pycurl-дескриптором напрямую. Пример:
from grab import Grab
import pycurl
g = Grab()
g.curl.setopt(pycurl.RANGE, '100-200')
g.go('http://some/url')
http://docs.grablib.org/grab/misc.html#pycurl
но в последней версии нету g.curl свойства, хранится оно теперь в g.transport.curl как я понимаю.
Redirect =HTTP 301 and 302 Redirects, Meta Refresh Redirect
For Examples:
request www.a.com and saved Cookie: a=123
when www.a.com redirect www.b.com
reuse_cookies = True or reuse_cookies = False
cookies will be sended to www.b.com. They are a different domain,but www.a.com site's cookie will be sended www.b.com
I am sorry for my poor english.
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
Из-за response.parse в prepare_response файла curl.py большие файлы считываются в память, несмотря на опцию body_inmemory=False. Скорей всего виновата строчка if isinstance(self.body, unicode): в методе parse класса Response
Возможно это уже реализовано, но в документации не нашел, а если этого нет - возможно интересно добавить.
Было бы неплохо реализовать скачивание картинок (само собой не всех, а только нужных) из полученных HTML с последующей автоматической заменой оригинальных ссылок на картинки на новые, которые указывают на картинки уже на нашем сервере.
Please, update docs about proxies
https://www.evernote.com/shard/s168/sh/73409195-9dae-4f65-85aa-0e7e77703a02/9ecf57575cb6dd33f9c5a11a49d012e3
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
The current Grab documentation is in Russian language. It should be translated to English.
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
Во всей документации, что я нашёл, было указано, что ручное указание character set для страницы должно быть произведено с помощью charset параметра grab. Это заводит в заблуждение, потому что в действительности, судя по коду, за это отвечает параметр document_charset, а charset - это то, в какую локаль нужно конвертировать скачанную страницу. Думаю, это стоит поправить и пояснить.
Привет.
Собери, пожалуйста, пакет для pypi так что-бы pycurl и lxml ставились сами по команде pip install grab
Скажите, как я могу обработать ошибку: ERROR:grab.spider.base:Could not resolve host
Я создаю задачу для Spider
yield Task('check_domain', url=url)
Но если домен не резолвится то задача не выполняется, а как обработать такую ошибку?
P.S.
Понимаю что проблему возможно описал очень абстрактно, могу дать подробности, но только не знаю какие :)
Скажите, а возможно ли создание задачи без URL? В моём случае я хочу сделать запись данных в бд отдельной задаче, возможно ли это?
Иногда при поиске каких либо данных в теле ответа возникают исключения. Хотелось бы иметь возможность получить тело ответа в котором происходил поиск по regexp, xpath, text. Тогда появится возможность быстро исправлять ошибки. Это особенно актуально когда мы парсим сайты на которых довольно часто происходят изменения в верстке.
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
с 32 битными системами все проще, один добрый человек собрал курл под него, есть ли у вас возможность сделать тоже самое для x64? Мы тут всей командой мучаемся из за этого бага. Библиотека мощная и труда в нее вложено не мало, но она становится бесполезной при таком баге. Или возможно ли сделать его не на curl, а на сокетах к примеру.
Добрый день. Заметил что параметр request_pause был убран, объявлен устаревшим и более нигде не используется. Он был очень нужен. Подскажите как без него организовать работу спайдера так чтобы он допустим делал запросы не постоянно, а с паузой в 3-5 секунд допустим. Иначе владельцы ресурсов могут забанить такой такую активность.
Спасибо
Файл selector/selector.py строка 296 - написано pyquery вместо query
class PyquerySelector(LxmlNodeBaseSelector):
__slots__ = ()
def pyquery_node(self):
return PyQuery(self.node)
def process_query(self, query):
return self.pyquery_node().find(pyquery)
должно быть
def process_query(self, query):
return self.pyquery_node().find(query)
Обратил внимание на странное поведение clean_html:
Например, у нас есть html вроде
Text_part1
<img src="test_img.jpg" width="100%" alt="Test image" />
Text_part2
После применения clean_html(html, safe_attrs=('src', 'href')) img пропадает, не смотря на то, что атрибут src разрешен. Вероятно это происходит потому, что другие атрибуты, которые есть в img не разрешены.
Возможно не стоит удалять тег, если в нем есть хотя бы один разрешенный атрибут?
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
Branch name is v06: https://github.com/lorien/grab/tree/v06
Опечатка в методе Spider.get_name (файл grab/spider/base.py Line 950)
Соответственно, если я хочу использовать "разные" очереди mongo я делаю так:
bot = CustomSpider()
bot.spider_name = 'custom_spider-%s' % my_data_item.some_unique_id
bot.setup_queue(backend='mongo', database='some_db') # тут возникает ошибка из-за опечатки
bot.run()
grab (0.4.13)
Want to back this issue? Place a bounty on it! We accept bounties via Bountysource.
for item in grab.doc.select('//div[@class="item"]'):
a_name = item.select('//div[@class="nameRus"]/a').text()
datetime = item.select('//div[@class="date"]').text()
In this example '//' always searches from the begining of html document. I think that '//' in item.select should search only in item's chunk of html.
У меня grab стал выдавать вот такую ошибку иногда, раньше точно не было на более старых версиях, так как этот скрипт старый.
Traceback (most recent call last):
File "/root/yelp_spider/test_proxy.py", line 100, in <module>
main()
File "/root/yelp_spider/test_proxy.py", line 88, in main
p.run()
File "/root/yelp_spider/grab/spider/base.py", line 945, in run
self.transport.process_handlers()
File "/root/yelp_spider/grab/spider/transport/multicurl.py", line 68, in process_handlers
select.select(rlist, wlist, xlist, timeout / 1000.0)
select.error: (22, 'Invalid argument')
Код: http://dumpz.org/1129253/
Там grab-объекты создаются явным образом для того, что бы протестировать каждую проксю единожды.
Баг воспроизводится в случае, если последний таск отвалился по таймауту.
В функцию select.select передаются параметры
[24, 25] [] [] -0.001
Могу предположить, что это из-за отрицательного значения. Просьба проверить.
Код Spider-a:
http://dumpz.org/836121/
урл для теста: http://genomictechnicalsolutions.com/angazo/index.php/using-joomla/extensions/components/users-component/registration-form
Из pypi grab работает нормально. Установил из гитхаб - джумла пишет session has been expired.
Example:
http://docs.grablib.org/search.html?q=test&check_keywords=yes&area=default
Return:
404 Not Found
nginx/1.2.1
Для следующей формы формируется неправильный запрос.
Форма:
<!--<input type="hidden" name="md" value="move"/>-->
<!--<table>-->
<!--<tbody>-->
<!--<tr>-->
<!--<td><input type="checkbox" name="test" value="12##48" checked="checked"/></td>-->
<!--<td>Some value</td>-->
<!--</tr>-->
<!--<tr>-->
<!--<td><input type="checkbox" name="test" value="15##25" checked="checked"/></td>-->
<!--<td>Some value</td>-->
<!--</tr>-->
<!--<tr>-->
<!--<th>-->
<!--<button onclick="this.form.submit(); return false;">Submit</button>-->
<!--</th>-->
<!--</tr>-->
<!--</tbody>-->
<!--</table>-->
Вывод grab.network.log:
[01] GET http://localhost/
[02] POST http://localhost/
POST request
test <CheckboxValues {'12##48', '15##25'} for checkboxes name='test'>
md move
grab_fail.py:
g.go('http://localhost/')
g.choose_form(xpath=".//form[@id='info-form']")
g.submit()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.