使用scrapy抓取列出的HTML值

zphenhs4  于 2022-11-09  发布在  其他
关注(0)|答案(3)|浏览(185)

我似乎不知道如何构造这个xpath选择器。我甚至尝试过使用nextsibling::text,但是没有用。我也浏览过stackoverflow问题来抓取列出的值,但是不能正确实现它。我一直得到空白的结果。任何和所有的帮助都将是感激的。谢谢。
网站名称为https://www.unegui.mn/adv/5737502_10-r-khoroolold-1-oroo/

预期结果:

伍兹
2015

当前结果:

空白的

当前:XPath零碎代码:

如果您有任何问题,请与我们联系。如果您有问题,请与我们联系。
返回一个新的字符串,并将其添加到新的字符串中。
楼层类型=列表_li[0].strip()佣金_年=列表_li[1].strip()

HTML代码段:

<div class="announcement-characteristics clearfix">
  <ul class="chars-column">
    <li class="">
      <span class="key-chars">Flooring:</span>
      <span class="value-chars">Wood</span></li>
    <li class="">
      <span class="key-chars">Commission year:</span>
      <a href="https://www.unegui.mn/l-hdlh/l-hdlh-zarna/oron-suuts-zarna/1-r/ashon_min---2011/"class="value-chars">2015</a>
    </li>
  </ul>
</div>

**进一步澄清:**我以前使用了两个选择器(一个用于span列表,一个用于href列表),但问题是网站上的一些页面不遵循相同的span列表/a列表顺序(即,在一个页面上,表值将在span列表中,但在其他一些页面上,它将在href列表中)。这就是为什么我一直试图只使用一个选择器,并获得所有的值。

这会产生如下图所示的值。它不是擦除窗口数也就是一个整数,而是擦除地址,因为在某些页面上,表值在href列表下,而不是span列表下。x1c 0d1x

前2个选择器:

返回一个响应.xpath(“.//span[包含(@类,'值字符')]//文本()”).extract()
返回一个新的字符串,并将其添加到一个新的字符串中。
整个代码(如果有人需要它来测试它):


# -*- coding: utf-8 -*-

import scrapy
from scrapy import Request
from datetime import datetime
from scrapy.crawler import CrawlerProcess
from selenium import webdriver

dt_today = datetime.now().strftime('%Y%m%d')
filename = dt_today + ' UB HPI Buying Data'

# create Spider class

class UneguiApartmentsSpider(scrapy.Spider):
    name = "unegui_apts"
    allowed_domains = ["www.unegui.mn"]
    custom_settings = {
        "FEEDS": {
            f'{filename}.csv': {
                'format': 'csv',
                'overwrite': True}}
    }

    # function used for start url
    def start_requests(self):
        urls = ['https://www.unegui.mn/l-hdlh/l-hdlh-zarna/oron-suuts-zarna/ulan-bator/']
        for url in urls:
            yield Request(url, self.parse)

    def parse(self, response,**kwargs):
        cards = response.xpath("//li[contains(@class,'announcement-container')]")

        # parse details
        for card in cards:
            name = card.xpath(".//a[@itemprop='name']/@content").extract_first().strip()
            price = card.xpath(".//*[@itemprop='price']/@content").extract_first().strip()
            rooms = card.xpath("normalize-space(.//div[contains(@class,'announcement-block__breadcrumbs')]/span[2]/text())").extract_first().strip()
            link = card.xpath(".//a[@itemprop='url']/@href").extract_first().strip()
            date_block = card.xpath("normalize-space(.//div[contains(@class,'announcement-block__date')]/text())").extract_first().split(',')
            date = date_block[0].strip()
            city = date_block[1].strip()

            item = {'name': name,
                    'date': date,
                    'rooms': rooms,
                    'price': price,
                    'city': city,
                    }
            # follow absolute link to scrape deeper level
            yield response.follow(link, callback=self.parse_item, meta={'item': item})

        # handling pagination
        next_page = response.xpath("//a[contains(@class,'number-list-next js-page-filter number-list-line')]/@href").get()
        if next_page:
            yield response.follow(next_page, callback=self.parse)
            print(f'Scraped {next_page}')

    def parse_item(self, response):
        # retrieve previously scraped item between callbacks
        item = response.meta['item']

        # parse additional details
        list_li = response.xpath(".//*[contains(@class, 'value-chars')]/text()").extract()

        # get additional details from list of <span> tags, element by element
        floor_type = list_li[0].strip()
        num_balcony = list_li[1].strip()
        commission_year = list_li[2].strip()
        garage = list_li[3].strip()
        window_type = list_li[4].strip()
        num_floors = list_li[5].strip()
        door_type = list_li[6].strip()
        area_sqm = list_li[7].strip()
        floor = list_li[8].strip()
        leasing = list_li[9].strip()
        district = list_li[10].strip()
        num_window = list_li[11].strip()
        address = list_li[12].strip()

        #list_span = response.xpath(".//span[contains(@class,'value-chars')]//text()").extract()
        #list_a = response.xpath(".//a[contains(@class,'value-chars')]//text()").extract()

        # get additional details from list of <span> tags, element by element
        #floor_type = list_span[0].strip()
        #num_balcony = list_span[1].strip()
        #garage = list_span[2].strip()
        #window_type = list_span[3].strip()
        #door_type = list_span[4].strip()
        #num_window = list_span[5].strip()

        # get additional details from list of <a> tags, element by element
        #commission_year = list_a[0].strip()
        #num_floors = list_a[1].strip()
        #area_sqm = list_a[2].strip()
        #floor = list_a[3].strip()
        #leasing = list_a[4].strip()
        #district = list_a[5].strip()
        #address = list_a[6].strip()

        # update item with newly parsed data
        item.update({
            'district': district,
            'address': address,
            'area_sqm': area_sqm,
            'floor': floor,
            'commission_year': commission_year,
            'num_floors': num_floors,
            'num_windows': num_window,
            'num_balcony': num_balcony,
            'floor_type': floor_type,
            'window_type': window_type,
            'door_type': door_type,
            'garage': garage,
            'leasing': leasing
        })
        yield item

        def __init__(self):
            self.driver = webdriver.Firefox()

            def parse_item2(self, response):
                self.driver.get(response.url)

                while True:
                    next = self.driver.find_element_by_xpath(".//span[contains(@class,'phone-author__title')]//text()")
                    try:
                        next.click()
                        # get the data and write it to scrapy items
                    except:
                        break
                self.driver.close()

# main driver

if __name__ == "__main__":
    process = CrawlerProcess()
    process.crawl(UneguiApartmentsSpider)
    process.start()
cigdeys3

cigdeys31#

你需要两个选择器,一个传递键,另一个解析值。这将产生两个列表,可以压缩在一起,以便给予你你正在寻找的结果。
CSS选择器可以是:
键选择器--〉.chars-column li .key-chars值选择器--〉.chars-column li .value-chars
一旦提取了这两个列表,就可以压缩它们,并将它们作为键值使用。

r1zhe5dt

r1zhe5dt2#

使用此XPath获取Wood

//*[@class="chars-column"]//span[2]//text()

使用此XPath获取2015

//*[@class="chars-column"]//a[text()="2015"]
nhhxz33t

nhhxz33t3#

我想这是因为无效的HTML(一些span元素没有关闭),正常的xpath是不可能的。
这确实给了我结果:

".//*[contains(@class,'value-chars')]"

*意味着任意元素,因此它将同时选择select

<span class="value-chars">Wood</span>

<a href="https://www.unegui.mn/l-hdlh/l-hdlh-zarna/oron-suuts-zarna/1-r/ashon_min---2011/"class="value-chars">2015</a>

相关问题