2015-08-21 4 views
2

Я сейчас опробоваюсь. Я попробовал код примера на странице http://doc.scrapy.org/en/1.0/intro/overview.html. Я попытался извлечь последние вопросы с тегом «bigdata». Все работало хорошо. Но когда я пытался извлекать вопросы с помощью «bigdata» тегов и «python», результаты были неверными, и в результате возникали только теги «bigdata». Но в браузере я правильно задаю вопросы с обоими тегами. Вы можете найти код ниже:Scrapy сканирование stackoverflow вопросы, соответствующие нескольким тегам

import scrapy 

class StackOverflowSpider(scrapy.Spider): 
    name = 'stackoverflow' 
    start_urls = ['https://stackoverflow.com/questions/tagged/bigdata?page=1&sort=newest&pagesize=50'] 

    def parse(self, response): 
     for href in response.css('.question-summary h3 a::attr(href)'): 
      full_url = response.urljoin(href.extract()) 
      yield scrapy.Request(full_url, callback=self.parse_question) 

    def parse_question(self, response): 
     yield { 
      'title': response.css('h1 a::text').extract()[0], 
      'votes': response.css('.question .vote-count-post::text').extract()[0], 
      'body': response.css('.question .post-text').extract()[0], 
      'tags': response.css('.question .post-tag::text').extract(), 
      'link': response.url, 
     } 

Когда я изменяю start_urls в

start_urls = [ 'https://stackoverflow.com/questions/tagged/bigdata+python?page=1&sort=newest&pagesize=50']

результаты содержат вопросы с единственным тегом 'bigdata. Как получить вопросы только с тегами?

Редактировать: Я думаю, что происходит то, что scrapy идет на страницы с тегами 'bigdata' с главной страницы, которую я дал, потому что теги являются ссылками на главную страницу этого тега. Как я могу отредактировать этот код, чтобы сделать scrapy не вдаваться в страницы тегов и только вопросы на этой странице? Я пробовал использовать такие правила, как показано ниже, но результаты все еще не правильные.

rules = (Rule(LinkExtractor(restrict_css='.question-summary h3 a::attr(href)'), callback='parse_question'),) 

ответ

2

У вас есть (как и исходные правила css) правильно; или более просто:

start_urls = ['https://stackoverflow.com/questions/tagged/python+bigdata'] 

Экстраполируя this, это также будет работать:

start_urls = ['https://stackoverflow.com/questions/tagged/bigdata%20python'] 

этот вопрос вы работаете в однако, является то, что StackOverflow, кажется, требует, чтобы Вы вошли в доступа функция поиска нескольких тегов. Чтобы увидеть это, просто выйдите из сеанса stackoverflow и попробуйте использовать тот же URL-адрес в вашем браузере. Он перенаправит вас на страницу результатов только для первого из двух тегов.

TL; DR единственный способ получить несколько тегов особенность, как представляется, войдя в (исполнение с помощью сеансовых куки)

Таким образом, при использовании scrapy, то исправление для проверки подлинности сеанса (логин), прежде чем делать что-нибудь else, а затем перейти к разбору как обычно, и все это работает. Для этого вы можете использовать InitSpider вместо Spider и добавить соответствующие методы входа. Предполагая, что вы входите в систему с помощью StackOverflow напрямую (в отличие от Google и т. П.), Я смог заставить его работать так, как ожидалось:

import scrapy 
import getpass 
from scrapy.spiders.init import InitSpider 

class StackOverflowSpider(InitSpider): 
    name = 'stackoverflow' 
    login_page = 'https://stackoverflow.com/users/login' 
    start_urls = ['https://stackoverflow.com/questions/tagged/bigdata+python'] 

    def parse(self, response): 
     ... 

    def parse_question(self, response): 
     ... 

    def init_request(self): 
     return scrapy.Request(url=self.login_page, callback=self.login) 

    def login(self, response): 
     return scrapy.FormRequest.from_response(response, 
        formdata={'email': '[email protected]', 
           'password': getpass.getpass()}, 
        callback=self.check_login_response) 

    def check_login_response(self, response): 
     if "https://stackoverflow.com/users/logout" in response.body: 
      self.log("Successfully logged in") 
      return self.initialized() 
     else: 
      self.log("Failed login") 
+0

Спасибо. Это сработало отлично. –

Смежные вопросы