使用Scrapy进行Python递归抓取

2 投票
1 回答
5895 浏览
提问于 2025-04-17 21:20

我正在尝试制作一个抓取工具,用来提取craigslist上的链接、标题、价格和帖子内容。我已经能够获取价格,但它返回的是页面上每个列表的价格,而不是特定行的价格。我也无法让它继续到下一页进行抓取。

这是我正在使用的教程 - http://mherman.org/blog/2012/11/08/recursively-scraping-web-pages-with-scrapy/

我尝试了这个讨论中的建议,但仍然无法让它工作 - Scrapy Python Craigslist Scraper

我想抓取的页面是 - http://medford.craigslist.org/cto/

在链接价格的变量中,如果我去掉 // 在 span[@class="l2"] 前面,它就不会返回任何价格,但如果我保留它,就会包含页面上的每一个价格。

关于规则,我尝试过调整类标签,但似乎在第一页就卡住了。我在想我可能需要单独的爬虫类?

这是我的代码:

#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:
#
# Author:      CD
#
# Created:     02/03/2014
# Copyright:   (c) CD 2014
# Licence:     <your licence>
#-------------------------------------------------------------------------------
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from craigslist_sample.items import CraigslistSampleItem
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.http import Request
from scrapy.selector import *
import sys

class PageSpider(BaseSpider):
    name = "cto"
    allowed_domains = ["medford.craigslist.org"]
    start_urls = ["http://medford.craigslist.org/cto/"]

    rules = (Rule(SgmlLinkExtractor(allow=("index\d00\.html", ), restrict_xpaths=('//span[@class="button next"]' ,))
        , callback="parse", follow=True), )

    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        titles = hxs.select('//span[@class="pl"] | //span[@class="l2"]')

        for title in titles:
            item = CraigslistSampleItem()
            item['title'] = title.select("a/text()").extract()
            item['link'] = title.select("a/@href").extract()
            item['price'] = title.select('//span[@class="l2"]//span[@class="price"]/text()').extract()

            url = 'http://medford.craigslist.org{}'.format(''.join(item['link']))
            yield Request(url=url, meta={'item': item}, callback=self.parse_item_page)


    def parse_item_page(self, response):
        hxs = HtmlXPathSelector(response)

        item = response.meta['item']
        item['description'] = hxs.select('//section[@id="postingbody"]/text()').extract()
        return item

1 个回答

4

这个想法很简单:在一个 class="content"div 中找到所有的段落。然后从每个段落中提取出链接、文本链接和价格。需要注意的是,select() 方法现在已经不推荐使用了,建议用 xpath() 来代替。

下面是修改过的 parse() 方法的版本:

def parse(self, response):
    hxs = HtmlXPathSelector(response)
    rows = hxs.select('//div[@class="content"]/p[@class="row"]')

    for row in rows:
        item = CraigslistSampleItem()
        link = row.xpath('.//span[@class="pl"]/a')
        item['title'] = link.xpath("text()").extract()
        item['link'] = link.xpath("@href").extract()
        item['price'] = row.xpath('.//span[@class="l2"]/span[@class="price"]/text()').extract()

        url = 'http://medford.craigslist.org{}'.format(''.join(item['link']))
        yield Request(url=url, meta={'item': item}, callback=self.parse_item_page)

这是我得到的一个示例:

{'description': [u"\n\t\tHave a nice, sturdy, compact car hauler/trailer.  May be used for other hauling like equipstment, ATV's and the like,   Very solid and in good shape.   Parice to sell at only $995.   Call Bill at 541 944 2929 top see or Roy at 541 9733421.   \n\t"],
 'link': [u'/cto/4354771900.html'],
 'price': [u'$995'],
 'title': [u'compact sturdy car trailer ']}

希望这对你有帮助。

撰写回答