Scrapy爬取网站只需一层

3
我正在使用scrapy爬取一个域名下的所有网页。
我看到了这个问题:https://dev59.com/xV3Va4cB1Zd3GeqPFPGv。但是没有解决方案。我的问题似乎也很相似。我的爬取命令的输出结果如下:
scrapy crawl sjsu2012-02-22 19:41:35-0800 [scrapy] INFO: Scrapy 0.14.1 started (bot: sjsucrawler)
2012-02-22 19:41:35-0800 [scrapy] DEBUG: Enabled extensions: LogStats, TelnetConsole, CloseSpider, WebService, CoreStats, MemoryUsage, SpiderState
2012-02-22 19:41:35-0800 [scrapy] DEBUG: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware, DefaultHeadersMiddleware, RedirectMiddleware, CookiesMiddleware, HttpCompressionMiddleware, ChunkedTransferMiddleware, DownloaderStats
2012-02-22 19:41:35-0800 [scrapy] DEBUG: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMiddleware
2012-02-22 19:41:35-0800 [scrapy] DEBUG: Enabled item pipelines: 
2012-02-22 19:41:35-0800 [sjsu] INFO: Spider opened
2012-02-22 19:41:35-0800 [sjsu] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2012-02-22 19:41:35-0800 [scrapy] DEBUG: Telnet console listening on 0.0.0.0:6023
2012-02-22 19:41:35-0800 [scrapy] DEBUG: Web service listening on 0.0.0.0:6080
2012-02-22 19:41:35-0800 [sjsu] DEBUG: Crawled (200) <GET http://cs.sjsu.edu/> (referer: None)
2012-02-22 19:41:35-0800 [sjsu] INFO: Closing spider (finished)
2012-02-22 19:41:35-0800 [sjsu] INFO: Dumping spider stats:
    {'downloader/request_bytes': 198,
     'downloader/request_count': 1,
     'downloader/request_method_count/GET': 1,
     'downloader/response_bytes': 11000,
     'downloader/response_count': 1,
     'downloader/response_status_count/200': 1,
     'finish_reason': 'finished',
     'finish_time': datetime.datetime(2012, 2, 23, 3, 41, 35, 788155),
     'scheduler/memory_enqueued': 1,
     'start_time': datetime.datetime(2012, 2, 23, 3, 41, 35, 379951)}
2012-02-22 19:41:35-0800 [sjsu] INFO: Spider closed (finished)
2012-02-22 19:41:35-0800 [scrapy] INFO: Dumping global stats:
    {'memusage/max': 29663232, 'memusage/startup': 29663232}

这里的问题是爬虫可以从第一页找到链接,但不能访问它们。这样的爬虫有什么用呢?
编辑:
我的爬虫代码是:
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector

class SjsuSpider(BaseSpider):
    name = "sjsu"
    allowed_domains = ["sjsu.edu"]
    start_urls = [
        "http://cs.sjsu.edu/"
    ]

    def parse(self, response):
        filename = "sjsupages"
        open(filename, 'wb').write(response.body)

我所有的其它设定都是默认的。


你能展示一下“Spider”代码和“Rules”吗? - reclosedev
3个回答

10

我认为最好的方法是使用Crawlspider。因此,您需要修改代码以便从第一页找到所有链接并访问它们:

class SjsuSpider(CrawlSpider):

    name = 'sjsu'
    allowed_domains = ['sjsu.edu']
    start_urls = ['http://cs.sjsu.edu/']
    # allow=() is used to match all links
    rules = [Rule(SgmlLinkExtractor(allow=()), callback='parse_item')]

    def parse_item(self, response):
        x = HtmlXPathSelector(response)

        filename = "sjsupages"
        # open a file to append binary data
        open(filename, 'ab').write(response.body)

如果您想爬取网站中的所有链接(而不仅仅是第一层级别的链接),则需要添加一个规则来跟踪每个链接,因此您需要将规则变量更改为以下内容:
rules = [
    Rule(SgmlLinkExtractor(allow=()), follow=True),
    Rule(SgmlLinkExtractor(allow=()), callback='parse_item')
]

我已经将你的“parse”回调更改为“parse_item”,因为如下原因:
当撰写爬虫规则时,请避免使用“parse”作为回调,因为CrawlSpider自身使用“parse”方法来实现其逻辑。因此,如果您覆盖“parse”方法,则爬行蜘蛛将不再起作用。
要获取更多信息,请参见:http://doc.scrapy.org/en/0.14/topics/spiders.html#crawlspider

尝试将callback='parse_item'更改为callback=('parse_item'),或者将规则更改为: rules = [ Rule(SgmlLinkExtractor(allow=()), follow=True,callback=('parse_item') ] - Thanasis Petsas
此外,在声明爬虫之前打开文件并仅在parse_item中调用write方法是一个好主意。您可以在爬虫类之前添加以下内容:myfile = open(filename,'ab'),并且在parse_item中可以使用此代码:myfile.write(response.body)。在写入后,您可以使用flush函数强制刷新文件中的数据:myfile.flush()。 - Thanasis Petsas
2
allow=() 不起作用,因为 Rule 的内部是基于匹配的,即如果您想处理所有 URL,请将 Rule(SgmlLinkExtractor(allow=('.+',)), callback='parse_item') 放入其中。不要忘记逗号,因为它需要一个元组。 - goh
@goh,为了避免错过微妙的逗号/元组,scrapy代码示例使用列表,例如Rule(SgmlLinkExtractor(allow=['.+']), callback='parse_item')。此外,我可以确认@ThanasisPetsas答案中的第二个规则不会调用回调函数,回调函数必须在具有follow=True的规则中设置,就像你所做的那样,@goh。但是,由于我对Scrapy还不熟悉,我不确定是否应该编辑答案中的错误代码。 - hobs

2
如果您正在使用 BaseSpider,在解析方法/回调中,您需要提取所需的 URL 并返回 Request 对象,如果您打算访问这些 URL。请注意保留 HTML 标签。
for url in hxs.select('//a/@href').extract():
            yield Request(url, callback=self.parse)

"parse"的作用是返回响应结果,您需要告诉它您想要做什么。在文档中有说明。

或者,如果您希望使用CrawlSpider,那么您只需为您的爬虫定义规则即可。


1
谢谢。我在文档中看到了,但是教程没有提到任何关于它的内容,我假设它将爬取允许域名下树形结构中的所有网页。我还没有测试过。但我一定会告诉你的。顺便再次感谢。 - hrishikeshp19

0

只是以防万一这对你有用。当爬虫像这种情况下不工作时,请确保从你的爬虫文件中删除以下代码。这是因为爬虫默认会调用该方法,如果它在文件中被声明了。

def parse(self, response):
  pass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接