Здесь мы вставляем в разные модули "import pdb; pdb.set_trace()" и учимся разбирать чужой код. Конечно, хорошо бы проникнуть в замыслы автора, или, хотя бы, понять структуру папок... Но пока легко удается при помощи "where" только находить и просматривать модули стека. Но, чтобы понять принципы работы программы, логику...
Поскольку замыслами все довольно сложно, потому надо бы изучить правила для папок Django (которые многие используют)... может быть это поможет?
Поскольку замыслами все довольно сложно, потому надо бы изучить правила для папок Django (которые многие используют)... может быть это поможет?
Здесь в 16 строке я вставил pdb.set_trace() - команду вызова дебаггера из кода¶
In [1]:
%load 'C:\\Users\\kiss\\Documents\\GitHub\\dirbot_se1\\dirbot\\randomproxy.py'
In []:
import re
import random
import base64
from scrapy import log
# debugger
import pdb
class RandomProxy(object):
def __init__(self, settings):
self.proxy_list = settings.get('PROXY_LIST')
fin = open(self.proxy_list)
self.proxies = {}
for line in fin.readlines():
parts = re.match('(\w+://)(\w+:\w+@)?(.+)', line)
pdb.set_trace() # line 16
# Cut trailing @
if parts[1]:
parts[1] = parts[1][:-1]
self.proxies[parts[0] + parts[2]] = parts[1]
fin.close()
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings)
def process_request(self, request, spider):
# Don't overwrite with a random one (server-side state for IP)
if 'proxy' in request.meta:
return
proxy_address = random.choice(self.proxies.keys())
proxy_user_pass = self.proxies[proxy_address]
request.meta['proxy'] = proxy_address
if proxy_user_pass:
basic_auth = 'Basic ' + base64.encodestring(proxy_user_pass)
request.headers['Proxy-Authorization'] = basic_auth
def process_exception(self, request, exception, spider):
proxy = request.meta['proxy']
log.msg('Removing failed proxy <%s>, %d proxies left' % (
proxy, len(self.proxies)))
try:
del self.proxies[proxy]
except ValueError:
pass
Когда дебаггер подключился, я запустил команду where (и получил стек)¶
Я оценил возможности дебаггера, когда не смог запустить дебаггер сразу из командной строки. Здесь уже есть довольно "сложный вызов" "scrapy crawl dmoz". Поэтому и пришлось перечитать руководство по pdb и использовать pdb.set_trace()
In []:
C:\Users\kiss\Documents\GitHub\dirbot_se1>scrapy crawl dmoz
2014-04-25 09:40:19+0400 [scrapy] INFO: Scrapy 0.20.1 started (bot: scrapybot)
2014-04-25 09:40:19+0400 [scrapy] DEBUG: Optional features available: ssl, http11, boto, django
2014-04-25 09:40:19+0400 [scrapy] DEBUG: Overridden settings: {'DEFAULT_ITEM_CLASS': 'dirbot.items.Website', 'NEWSPIDER_MODULE': 'di
rbot.spiders', 'SPIDER_MODULES': ['dirbot.spiders'], 'RETRY_TIMES': 10, 'RETRY_HTTP_CODES': [500, 503, 504, 400, 403, 404, 408]}
2014-04-25 09:40:24+0400 [scrapy] DEBUG: Enabled extensions: LogStats, TelnetConsole, CloseSpider, WebService, CoreStats, SpiderStat
e
> c:\users\kiss\documents\github\dirbot_se1\dirbot\randomproxy.py(18)__init__()
-> if parts[1]:
(Pdb) where
c:\users\kiss\anaconda\lib\runpy.py(162)_run_module_as_main()
-> "__main__", fname, loader, pkg_name)
c:\users\kiss\anaconda\lib\runpy.py(72)_run_code()
-> exec code in run_globals
c:\users\kiss\anaconda\lib\site-packages\scrapy\cmdline.py(168)<module>()
-> execute()
c:\users\kiss\anaconda\lib\site-packages\scrapy\cmdline.py(143)execute()
-> _run_print_help(parser, _run_command, cmd, args, opts)
c:\users\kiss\anaconda\lib\site-packages\scrapy\cmdline.py(89)_run_print_help()
-> func(*a, **kw)
c:\users\kiss\anaconda\lib\site-packages\scrapy\cmdline.py(150)_run_command()
-> cmd.run(args, opts)
c:\users\kiss\anaconda\lib\site-packages\scrapy\commands\crawl.py(50)run()
-> self.crawler_process.start()
c:\users\kiss\anaconda\lib\site-packages\scrapy\crawler.py(92)start()
-> if self.start_crawling():
c:\users\kiss\anaconda\lib\site-packages\scrapy\crawler.py(124)start_crawling()
-> return self._start_crawler() is not None
c:\users\kiss\anaconda\lib\site-packages\scrapy\crawler.py(139)_start_crawler()
-> crawler.configure()
c:\users\kiss\anaconda\lib\site-packages\scrapy\crawler.py(47)configure()
-> self.engine = ExecutionEngine(self, self._spider_closed)
c:\users\kiss\anaconda\lib\site-packages\scrapy\core\engine.py(63)__init__()
-> self.downloader = Downloader(crawler)
c:\users\kiss\anaconda\lib\site-packages\scrapy\core\downloader\__init__.py(77)__init__()
-> self.middleware = DownloaderMiddlewareManager.from_crawler(crawler)
c:\users\kiss\anaconda\lib\site-packages\scrapy\middleware.py(50)from_crawler()
-> return cls.from_settings(crawler.settings, crawler)
c:\users\kiss\anaconda\lib\site-packages\scrapy\middleware.py(31)from_settings()
-> mw = mwcls.from_crawler(crawler)
c:\users\kiss\documents\github\dirbot_se1\dirbot\randomproxy.py(27)from_crawler()
-> return cls(crawler.settings)
> c:\users\kiss\documents\github\dirbot_se1\dirbot\randomproxy.py(18)__init__()
-> if parts[1]:
(Pdb)
In []:
(Pdb) args
self = <dirbot.randomproxy.RandomProxy object at 0x0000000004A7C3C8>
settings = <CrawlerSettings module=<module 'dirbot.settings' from 'dirbot\settings.pyc'>>
(Pdb)
Пока ясно только то, что в Scrapy не все так просто с формированием стека. В частности, есть три пути поиска настроек 6.1.2. The Module Search Path Но не ясно, как и когда берутся настройки из settings.py проекта.
Потому закоментируем в randomproxy.py строчки "import pdb" и "pdb.set_trace() " и запустим дебаггер из settings.py
А для этого:
Потому закоментируем в randomproxy.py строчки "import pdb" и "pdb.set_trace() " и запустим дебаггер из settings.py
А для этого:
Теперь вставим строку "import pdb; pdb.set_trace()" в файл settings.py¶
In [2]:
%load 'C:\\Users\\kiss\\Documents\\GitHub\\dirbot_se1\\dirbot\\settings.py' после строчки ########
In []:
# Scrapy settings for dirbot project
SPIDER_MODULES = ['dirbot.spiders']
NEWSPIDER_MODULE = 'dirbot.spiders'
DEFAULT_ITEM_CLASS = 'dirbot.items.Website'
ITEM_PIPELINES = ['dirbot.pipelines.FilterWordsPipeline']
##############################################
import pdb; pdb.set_trace()
# Retry many times since proxies often fail
RETRY_TIMES = 10
# Retry on most error codes since proxies fail for different reasons
RETRY_HTTP_CODES = [500, 503, 504, 400, 403, 404, 408]
DOWNLOADER_MIDDLEWARES = {
'scrapy.contrib.downloadermiddleware.retry.RetryMiddleware': 90,
# Fix path to this module
'dirbot.randomproxy.RandomProxy': 100,
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 110,
}
# Proxy list containing entries like
# http://host1:port
# http://username:password@host2:port
# http://host3:port
# ...
PROXY_LIST = 'dirbot/list.txt'
И спроси дебаггер, как мы сюда попали¶
In []:
C:\Users\kiss\Documents\GitHub\dirbot_se1>scrapy crawl dmoz
> c:\users\kiss\documents\github\dirbot_se1\dirbot\settings.py(11)<module>()
-> RETRY_TIMES = 10
(Pdb) where
c:\users\kiss\anaconda\lib\runpy.py(162)_run_module_as_main()
-> "__main__", fname, loader, pkg_name)
c:\users\kiss\anaconda\lib\runpy.py(72)_run_code()
-> exec code in run_globals
c:\users\kiss\anaconda\lib\site-packages\scrapy\cmdline.py(168)<module>()
-> execute()
c:\users\kiss\anaconda\lib\site-packages\scrapy\cmdline.py(109)execute()
-> settings = get_project_settings()
c:\users\kiss\anaconda\lib\site-packages\scrapy\utils\project.py(58)get_project_settings()
-> settings_module = import_module(settings_module_path)
c:\users\kiss\anaconda\lib\importlib\__init__.py(37)import_module()
-> __import__(name)
> c:\users\kiss\documents\github\dirbot_se1\dirbot\settings.py(11)<module>()
-> RETRY_TIMES = 10
(Pdb)
Удачно я сменил вход в дебаггер. Начло такое же ..162-..72-..168, а делее в cmdline -109. Ранее последовательность вызова аргументов в cmdline.py была другой (см выше)... Причина в том, что дополнительные настройки в settings.py еще не загружены.
Вот строки 106-119 из файла cmdline.py:
Вот строки 106-119 из файла cmdline.py:
In []:
# ------------------------------------------------------------------
if settings is None:
settings = get_project_settings()
check_deprecated_settings(settings)
# --- backwards compatibility for scrapy.conf.settings singleton ---
import warnings
from scrapy.exceptions import ScrapyDeprecationWarning
with warnings.catch_warnings():
warnings.simplefilter("ignore", ScrapyDeprecationWarning)
from scrapy import conf
conf.settings = settings
# ------------------------------------------------------------------
Сработало условие "if settings is None:", поскольку (наверное) выполнены только те строки кода, которые были сгенерированы автоматически. А то, что добавлено далее (полсе ######) и есть те настройки, которые вызывают аргументы (строки) 143 - 89 - 150... в файле (модуле) cmdline.py
Такое впечатление, что этот модуль (cmdline.py) формирует настройки паука (глобальные + из проекта + опции из командной строки при запуске).
In []:
from scrapy.utils.project import inside_project, get_project_settings
Эта строчка импортирует (судя по названию) данные из файла settings.py проекта, посмотрим подробности... Вот строки 52-72 из файла C:-packages.py
In []:
def get_project_settings():
if ENVVAR not in os.environ:
project = os.environ.get('SCRAPY_PROJECT', 'default')
init_env(project)
settings_module_path = os.environ.get(ENVVAR)
if settings_module_path:
settings_module = import_module(settings_module_path)
else:
settings_module = None
settings = CrawlerSettings(settings_module)
# XXX: remove this hack
pickled_settings = os.environ.get("SCRAPY_PICKLED_SETTINGS_TO_OVERRIDE")
settings.overrides = pickle.loads(pickled_settings) if pickled_settings else {}
# XXX: deprecate and remove this functionality
for k, v in os.environ.items():
if k.startswith('SCRAPY_'):
settings.overrides[k[7:]] = v
return settings
Похоже, что наши предположения верны - здесь выбираются настройки (из трех мест). Пока нет смысла "копать глубже", но при желании можно запустить дебаггер из этих строчек...
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий