【问题标题】:In Scrapy, how to extract two groups in a regular expression into two different fields?在 Scrapy 中,如何将正则表达式中的两个组提取到两个不同的字段中?
【发布时间】:2017-11-04 20:50:21
【问题描述】:

我正在写一个蜘蛛trulia 来抓取Trulia.com 上待售房产的页面,例如https://www.trulia.com/property/1072559047-1860-Lombard-St-San-Francisco-CA-94123;当前版本可以在https://github.com/khpeek/trulia-scraper找到。

我正在使用Item Loaders 并使用re 关键字参数调用add_xpath 方法来指定要提取的正则表达式。在文档中的示例中,正则表达式中只有一个组和一个要提取到的字段。

但是,我实际上想定义两个组并将它们提取到两个单独的 Scrapy 字段中。这是parse_property_page 方法的“摘录”:

def parse_property_page(self, response):
    l = TruliaItemLoader(item=TruliaItem(), response=response)

    details = l.nested_css('.homeDetailsHeading')
    overview = details.nested_xpath('.//span[contains(text(), "Overview")]/parent::div/following-sibling::div[1]')
    overview.add_xpath('overview', xpath='.//li/text()')
    overview.add_xpath('area', xpath='.//li/text()', re=r'([\d,]+) sqft$')
    overview.add_xpath('lot_size', xpath='.//li/text()', re=r'([\d,]+) (acres|sqft) lot size$')

注意lot_size 字段如何提取两组:一组用于数字,一组用于单位,可以是“英亩”或“平方英尺”。如果我使用命令运行这个parse 方法

scrapy parse https://www.trulia.com/property/1072559047-1860-Lombard-St-San-Francisco-CA-94123 --spider=trulia --callback=parse_property_page

然后我得到以下抓取的项目:

# Scraped Items  ------------------------------------------------------------
[{'address': '1860 Lombard St',
  'area': 2524.0,
  'city_state': 'San Francisco, CA 94123',
  'dates': ['10/22/2002', '04/25/2002', '03/20/2000'],
  'description': ['Outstanding investment opportunity to own this light-fixer '
                  'mixed use Marina 2-unit property w/established income and '
                  'not on liquefaction. The first floor of this building '
                  'houses a commercial business currently leased to Jigalin '
                  'Fitness until 2018. The second floor presents a 2bed/1bath '
                  'apartment fully outfitted in a contemporary design w/full '
                  'kitchen, 10ft high ceilings & laundry area. The apartment '
                  'will be delivered vacant. The structure has undergone '
                  'renovation & features concrete perimeter foundation, '
                  'reinforced walls, ADA compliant commercial restroom, '
                  'electrical updates & rolling door. This property makes an '
                  "ideal investment with instant cash flow. Don't let this "
                  'pass you by. As-Is sale.'],
  'events': ['Sold', 'Sold', 'Sold'],
  'listing_information': ['2 Bedrooms', 'Multi-Family'],
  'listing_information_date_updated': '11/03/2017',
  'lot_size': ['1620', 'sqft'],
  'neighborhood': 'Marina',
  'overview': ['Multi-Family',
               '2 Beds',
               'Built in 1908',
               '1 days on Trulia',
               '1620 sqft lot size',
               '2,524 sqft',
               '$711/sqft'],
  'prices': ['$850,000', '$1,350,000', '$1,200,000'],
  'public_records': ['1 Bathroom',
                     'Multi-Family',
                     '1,296 Square Feet',
                     'Lot Size: 1,620 sqft'],
  'public_records_date_updated': '07/01/2017',
  'url': 'https://www.trulia.com/property/1072559047-1860-Lombard-St-San-Francisco-CA-94123'}]

lot_size 字段是一个包含数字和单位的列表。但是,理想情况下,我希望将单位(英亩或平方英尺)提取到单独的字段lot_size_units。我可以通过首先加载项目并进行自己的处理来做到这一点,但我想知道是否有一种更加 Scrapy-native 的方式将匹配的组“解包”到不同的项目中?

(我已经仔细阅读了 https://github.com/scrapy/scrapy/blob/129421c7e31b89b9b0f9c5f7d8ae59e47df36091/scrapy/loader/init.py 上的 get_value 方法,但如果有的话,这还没有“告诉我方法”)。

【问题讨论】:

    标签: python scrapy


    【解决方案1】:

    你可以试试这个(一次忽略一组):

    overview.add_xpath('lot_size', xpath='.//li/text()', re=r'([\d,]+) (?:acres|sqft) lot size$')
    overview.add_xpath('lot_size_units', xpath='.//li/text()', re=r'(?:[\d,]+) (acres|sqft) lot size$')
    

    【讨论】:

    • 我意识到这一点,但这并不是 DRY,因为您实际上是在重复相同的正则表达式,但使用不同的组。我想我所设想的是一个xpath API,它接受一个元组作为field_name 参数,并将正则表达式中匹配的多个组“解包”到这个列表中。
    • 你是对的,但就像聪明人已经说过的那样“过早的优化是万恶之源”。我在 html 源代码中看不到任何可以帮助您区分每个部分的内容(除非它们始终是固定位置),唯一的另一种选择是使用外部正则表达式在 ItemLoader 之外执行所有提取(就像它由ItemLoader) 完成并使用add_value 方法添加每个字段,但这可能比当前解决方案更容易出错。其他替代方法(例如在 xpath 中使用正则表达式)将产生相同的结果。
    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 2013-01-22
    • 2020-04-03
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多