使用scrapy抓取雅虎小组时遇到问题

4 投票
1 回答
2143 浏览
提问于 2025-04-16 11:12

我刚开始接触网页抓取,正在尝试使用Scrapy,这是一个用Python写的抓取框架。我的目标是抓取一个旧的Yahoo小组,因为他们没有提供API或者其他方式来获取消息存档。这个Yahoo小组设置成需要登录才能查看存档。

我认为我需要完成的步骤是:

  1. 登录Yahoo
  2. 访问第一条消息的链接并抓取它
  3. 对下一条消息重复步骤2,以此类推

我开始粗略地写一个Scrapy爬虫来完成上述任务,下面是我目前的进展。我只想确认登录是否成功,并且能否获取到第一条消息。一旦这个部分工作正常,我会继续完成其他的:

class Sg101Spider(BaseSpider):
    name = "sg101"
    msg_id = 1              # current message to retrieve
    max_msg_id = 21399      # last message to retrieve

    def start_requests(self):
        return [FormRequest(LOGIN_URL,
            formdata={'login': LOGIN, 'passwd': PASSWORD},
            callback=self.logged_in)]

    def logged_in(self, response):
        if response.url == 'http://my.yahoo.com':
            self.log("Successfully logged in. Now requesting 1st message.")
            return Request(MSG_URL % self.msg_id, callback=self.parse_msg,
                    errback=self.error)
        else:
            self.log("Login failed.")

    def parse_msg(self, response):
        self.log("Got message!")
        print response.body

    def error(self, failure):
        self.log("I haz an error")

但是当我运行这个爬虫时,我看到它登录并请求第一条消息。然而,在Scrapy的调试输出中,我只看到3次重定向,最后到达我最开始请求的链接。但Scrapy并没有调用我的parse_msg()回调函数,爬取就停止了。这里是Scrapy输出的一部分:

2011-02-03 19:50:10-0600 [sg101] INFO: Spider opened
2011-02-03 19:50:10-0600 [sg101] DEBUG: Redirecting (302) to <GET https://login.yahoo.com/config/verify?.done=http%3a//my.yahoo.com> from <POST https://login.yahoo.com/config/login>
2011-02-03 19:50:10-0600 [sg101] DEBUG: Redirecting (meta refresh) to <GET http://my.yahoo.com> from <GET https://login.yahoo.com/config/verify?.done=http%3a//my.yahoo.com>
2011-02-03 19:50:12-0600 [sg101] DEBUG: Crawled (200) <GET http://my.yahoo.com> (referer: None)
2011-02-03 19:50:12-0600 [sg101] DEBUG: Successfully logged in. Now requesting 1st message.
2011-02-03 19:50:12-0600 [sg101] DEBUG: Redirecting (302) to <GET http://launch.groups.yahoo.com/group/MyYahooGroup/auth?done=http%3A%2F%2Flaunch.groups.yahoo.com%2Fgroup%2FMyYahooGroup%2Fmessage%2F1> from <GET http://launch.groups.yahoo.com/group/MyYahooGroup/message/1>
2011-02-03 19:50:12-0600 [sg101] DEBUG: Redirecting (302) to <GET http://launch.groups.yahoo.com/group/MyYahooGroup/auth?check=G&done=http%3A%2F%2Flaunch%2Egroups%2Eyahoo%2Ecom%2Fgroup%2FMyYahooGroup%2Fmessage%2F1> from <GET http://launch.groups.yahoo.com/group/MyYahooGroup/auth?done=http%3A%2F%2Flaunch.groups.yahoo.com%2Fgroup%2FMyYahooGroup%2Fmessage%2F1>
2011-02-03 19:50:13-0600 [sg101] DEBUG: Redirecting (302) to <GET http://launch.groups.yahoo.com/group/MyYahooGroup/message/1> from <GET http://launch.groups.yahoo.com/group/MyYahooGroup/auth?check=G&done=http%3A%2F%2Flaunch%2Egroups%2Eyahoo%2Ecom%2Fgroup%2FMyYahooGroup%2Fmessage%2F1>
2011-02-03 19:50:13-0600 [sg101] INFO: Closing spider (finished)
2011-02-03 19:50:13-0600 [sg101] INFO: Spider closed (finished)

我对此感到困惑。看起来Yahoo在重定向爬虫(可能是为了身份验证检查?),但它似乎又回到了我最开始想访问的链接。不过Scrapy没有调用我的回调函数,我没有机会去抓取数据或继续爬取。

有没有人知道发生了什么,或者如何进一步调试这个问题?谢谢!

1 个回答

5

我觉得Yahoo在进行授权检查时会进行重定向,最后会把我带回我真正想要访问的页面。不过,Scrapy已经看到这个请求了,它会停止处理,因为它不想陷入一个循环中。对我来说,解决办法是给请求构造器加上dont_filter=True。这样可以告诉Scrapy不要过滤掉重复的请求。对我来说这样没问题,因为我提前就知道我想要爬取哪些网址。

def logged_in(self, response):
    if response.url == 'http://my.yahoo.com':
        self.log("Successfully logged in. Now requesting message page.",
                level=log.INFO)
        return Request(MSG_URL % self.msg_id, callback=self.parse_msg,
                errback=self.error, dont_filter=True)
    else:
        self.log("Login failed.", level=log.CRITICAL)

撰写回答