python Scrapy CrawlSpider: правило не применяется после входа в систему, просматривается только первая страница

Я программист C/C++ с ограниченным опытом работы с Python в создании графиков и обработке текста. В настоящее время я работаю над проектом анализа личных данных и использую Scrapy для сканирования всех тем и информации о пользователях на форуме.

Я собрал исходный код, чтобы сначала войти в систему, а затем начать со страницы индексации подфорума, выполнив следующие действия:

1) извлечь все ссылки на темы, которые содержат "тему"

2) пока сохраните страницу в файле (информация об элементе будет извлечена, как только весь процесс заработает)

3) найдите ссылку на следующую страницу с тегом class=next, перейдите на следующую страницу и повторите 1) и 2)

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

Однако мой текущий код будет извлекать только все потоки в начальном URL-адресе, а затем останавливается. Я искал несколько часов и не нашел решения для этого. Поэтому я задаю свой вопрос здесь и надеюсь, что кто-то, имеющий опыт работы со Scrapy, может помочь мне здесь. Если вам, ребята, нужна какая-либо другая информация, такая как вывод, пожалуйста, дайте мне знать. Спасибо!

Что касается ответа Пола, я обновил свой код, что-то не так с моим экстрактором ссылок, мне нужно это исправить. Кроме этого, правило теперь работает нормально. Еще раз спасибо за помощь Павла.

Вот мой текущий код паука:

from scrapy.contrib.spiders import CrawlSpider
from scrapy.http import Request, FormRequest
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.spiders import Rule
from scrapy.selector import Selector

class ZhuaSpider(CrawlSpider):
    name = 'zhuaspider'
    allowed_domains = ['depressionforums.org']
    login_page = 'http://www.domain.com/forums/index.php?app=core&module=global&section=login'
    start_urls = ['http://www.depressionforums.org/forums/forum/12-depression-central/']

    rules = (Rule(SgmlLinkExtractor(restrict_xpaths=('//li[@class="next"]'), unique=True),
                           callback='parse_links',
                           follow=True),
            )

    def start_requests(self):
        """called before crawling starts. Try to login"""
        yield Request(
                url=self.login_page,
                callback=self.login,
                dont_filter=True)

    def login(self, response):
        """Generate a login request."""
        return FormRequest.from_response(response,
                formdata={'ips_username': 'myuid', 'ips_password': 'mypwd'},
                callback=self.check_login_response)

    def check_login_response(self, response):
        """Check the response returned by a login request to see if we are successfully logged in."""
        if "Username or password incorrect" in response.body:
            self.log("Login failed.")
        else:
            self.log("Successfully logged in. Let's start crawling!")
            # Now the crawling can begin.
            for url in self.start_urls:
                # explicitly ask Scrapy to run the responses through rules
                yield Request(url, callback=self.parse)

    def parse_links(self, response):
        hxs = Selector(response)
        links = hxs.xpath('//a[contains(@href, "topic")]')
        for link in links:
            title = ''.join(link.xpath('./@title').extract())
            url = ''.join(link.xpath('./@href').extract())
            meta={'title':title,}
            yield Request(url, callback = self.parse_posts, meta=meta,)

    #If I add this line it will only crawl the starting url,
    #otherwise it still won't apply the rule and crawls nothing.
    parse_start_url = parse_links

    def parse_posts(self, response):
        filename = 'download/'+ response.url.split("/")[-2]
        open(filename, 'wb').write(response.body)

person yzhwang    schedule 28.05.2014    source источник


Ответы (1)


Чтобы использовать Rules CrawlSpider, вам нужно, чтобы Requests обрабатывался внутренним методом parse().

Вы можете сделать это, явно установив callback=self.parse или не устанавливая обратный вызов.

start_urls = ['http://www.depressionforums.org/forums/forum/12-depression-central/']

rules = (
    Rule(SgmlLinkExtractor(restrict_xpaths=('//li[@class="next"]'), unique=True),
                           callback='parse_links',
                           follow=True),
)

...

def check_login_response(self, response):
    """Check the response returned by a login request to see if we are successfully logged in."""
    if "Username or password incorrect" in response.body:
        self.log("Login failed.")
    else:
        self.log("Successfully logged in. Let's start crawling!")
        # Now the crawling can begin.
        for url in self.start_urls:
            # explicitly ask Scrapy to run the responses through rules
            yield Request(url, callback=self.parse)

Только после этого вы должны увидеть страницы со ссылками в //li[@class="next"] разделах, которые сканируются и анализируются с использованием parse_links()... за исключением самих start_urls.

Чтобы пройти через parse_links для start_urls, необходимо определить специальный parse_start_url.

Ты можешь сделать это:

def parse_links(self, response):
    hxs = Selector(response)
    links = hxs.xpath('//a[contains(@href, "topic")]')
    for link in links:
        title = ''.join(link.xpath('./@title').extract())
        url = ''.join(link.xpath('./@href').extract())
        meta={'title':title,}
        yield Request(url, callback = self.parse_posts, meta=meta,)

parse_start_url = parse_links
person paul trmbrth    schedule 28.05.2014
comment
Спасибо, Пол! Я попробовал ваш метод, но он не будет применять правила. После того, как я изменил обратный вызов в функции check_login_response на self.parse, он ничего не сканирует. Если я добавлю parse_start_url = parse_links, он будет сканировать начальный URL-адрес. Вы знаете, почему это происходит? Еще раз спасибо за своевременный ответ. - person yzhwang; 28.05.2014
comment
Мне пришлось запустить его самому, чтобы увидеть проблему: вам нужно определить свои правила в атрибуте rules как кортеж. Посмотреть отредактированный код - person paul trmbrth; 28.05.2014
comment
Спасибо, Пол, я определил кортеж правил, и он работает. Что ж, теперь я знаю, что в моем экстракторе ссылок есть ошибка, потому что он не извлекает правильные ссылки, но я думаю, что исправлю это сам. Большое спасибо! - person yzhwang; 28.05.2014
comment
Спасибо, это мне очень помогает. - person yuxia; 21.06.2016