【问题标题】:How to parse JSON data in scrapy如何在scrapy中解析JSON数据
【发布时间】:2015-09-24 02:49:30
【问题描述】:

我在 Scrapy 中编写了一个 webscraper,它最初会转到 this 网页,抓取每张票的票信息,然后抓取“票”按钮重定向到的每个链接。在门票页面上,为了获得价格,必须请求 JSON file(现在这不是什么大问题),并且需要提取文件中的第一个价格并将其保存到 Scrapy 项目加载器中.

我尝试使用以下语句在 scrapy shell 中查找价格对象:

    jsonresponse = json.loads(response.body_as_unicode())
    jsonresponse["p"]

    jsonresponse["lp"]

    jsonresponse['hp']

但由于某种原因,他们都没有在文件中找到价格对象。如果您查看tickets page,您可以看到目前最低价格为 28 美元。对于这个特定的链接,我需要得到 $28 的字符串。

我知道scrapy 不处理javascript,并且scrapy.js 可用于将js 集成到scrapy 中,但我不确定是否应该在这种情况下使用它。无论如何,找到该对象并将其提取到变量中的正确方法是什么。任何帮助,将不胜感激。谢谢! [编辑] 这是到目前为止的代码:

bandname = raw_input("Enter a bandname \n")
vs_url = "http://www.vividseats.com/concerts/" + bandname + "-tickets.html"

class MySpider(CrawlSpider):
    handle_httpstatus_list = [416]
    name = 'comparator'
    allowed_domains = ["www.vividseats.com"]
    start_urls = [vs_url]
    tickets_list_xpath = './/*[@itemtype="http://schema.org/Event"]'
def parse_json(self, response):
        loader = response.meta['loader']
        #not sure what to put here yet
        return loader.load_item()

def parse_price(self, response):
        loader = response.meta['loader']
        ticketLink = loader.get_output_value("ticketsLink")
        json_id_list= re.findall(r"\d{2,9}", ticketsLink)
        json_id=  "".join(json_id_list)
        json_url = "www.vividseats.com/javascript/tickets.shtml?productionId=" + json_id
        yield scrapy.Request(json_url, meta={'loader': loader}, callback = self.parse_json, dont_filter = True) 

def parse(self, response):
    """
    """
   selector = HtmlXPathSelector(response)
        # iterate over tickets
        for ticket in selector.select(self.tickets_list_xpath):

            loader = XPathItemLoader(ComparatorItem(), selector=ticket)
            # define loader
            loader.default_input_processor = MapCompose(unicode.strip)
            loader.default_output_processor = Join()
            # iterate over fields and add xpaths to the loader

            loader.add_xpath('eventName' , './/*[@class="productionsEvent"]/text()')
            loader.add_xpath('eventLocation' , './/*[@class = "productionsVenue"]/span[@itemprop  = "name"]/text()')
            loader.add_xpath('ticketsLink' , './/*/a[@class = "btn btn-primary"]/@href')
            loader.add_xpath('eventDate' , './/*[@class = "productionsDate"]/text()')
            loader.add_xpath('eventCity' , './/*[@class = "productionsVenue"]/span[@itemprop  = "address"]/span[@itemprop  = "addressLocality"]/text()')
            loader.add_xpath('eventState' , './/*[@class = "productionsVenue"]/span[@itemprop  = "address"]/span[@itemprop  = "addressRegion"]/text()')
            loader.add_xpath('eventTime' , './/*[@class = "productionsTime"]/text()')
            print "Here is ticket link \n" + loader.get_output_value("ticketsLink")
            ticketsURL = "concerts/" + bandname + "-tickets/" + bandname + "-" + loader.get_output_value("ticketsLink")
            ticketsURL = urljoin(response.url, ticketsURL)
            yield scrapy.Request(ticketsURL, meta={'loader': loader}, callback = self.parse_price, dont_filter = True)

【问题讨论】:

  • 你能展示一下你目前拥有的完整代码吗?

标签: javascript python json web-scraping scrapy


【解决方案1】:

我们以this url为例;

所有门票信息对应上述链接位于here,从那里您只需将json的字段映射到html(html页面中的门票信息)。

In [1]: ticket_info = jsonresponse.get('tickets')

In [2]: ticket_info
Out[2]: 
 [{u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'1',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB844757004',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'27.00',
  u'q': u'3',
  u'r': u'G2',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'1',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'1',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB891598272',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'29.00',
  u'q': u'1',
  u'r': u'G3',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'0',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB900500475',
  u'ind': u'0',
  u'l': u'GA MAIN FLOOR',
  u'n': u'',
  u'p': u'30.00',
  u'q': u'2',
  u'r': u'G4',
  u'rhdn': u'0',
  u's': u'GA MAIN F..',
  u'sd': u'0',
  u't': u'0',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30613',
  u'd': u'3000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB886172318',
  u'ind': u'1',
  u'l': u'GA Second Balcony - Limited View',
  u'n': u'eTicket,Obstructed/Limited View Instant Download.',
  u'p': u'37.00',
  u'q': u'1',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA Second Balcony - Limited View',
  u'sd': u'0',
  u't': u'1',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'1',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB806449210',
  u'ind': u'1',
  u'l': u'GA MAIN FLOOR',
  u'n': u'eTicket Instant Download.',
  u'p': u'39.00',
  u'q': u'8',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA MAIN F..',
  u'sd': u'0',
  u't': u'1',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30612',
  u'd': u'2000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB900500473',
  u'ind': u'1',
  u'l': u'GA First Balcony',
  u'n': u'Instant Download.',
  u'p': u'46.00',
  u'q': u'2',
  u'r': u'G3',
  u'rhdn': u'0',
  u's': u'GA First Balcony',
  u'sd': u'0',
  u't': u'0',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB893201517',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'50.00',
  u'q': u'6',
  u'r': u'G5',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'3',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30615',
  u'd': u'995',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'07/19/15',
  u'i': u'VB900847659',
  u'ind': u'0',
  u'l': u'GA',
  u'n': u'Tickets will be ready for delivery by 07/19/2015.',
  u'p': u'53.00',
  u'q': u'4',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA',
  u'sd': u'0',
  u't': u'0',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30615',
  u'd': u'995',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'07/19/15',
  u'i': u'VB900847710',
  u'ind': u'0',
  u'l': u'GA',
  u'n': u'Tickets will be ready for delivery by 07/19/2015.',
  u'p': u'53.00',
  u'q': u'3',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA',
  u'sd': u'0',
  u't': u'0',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30612',
  u'd': u'2000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB900500474',
  u'ind': u'1',
  u'l': u'GA First Balcony',
  u'n': u'Instant Download.',
  u'p': u'57.00',
  u'q': u'8',
  u'r': u'G2',
  u'rhdn': u'0',
  u's': u'GA First Balcony',
  u'sd': u'0',
  u't': u'3',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB880887546',
  u'ind': u'0',
  u'l': u'GA Main Floor',
  u'n': u'eTicket',
  u'p': u'61.00',
  u'q': u'4',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'1',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB893198548',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'85.00',
  u'q': u'8',
  u'r': u'G4',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'3',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'0',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB893198623',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'94.00',
  u'q': u'2',
  u'r': u'G4',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'0',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'1',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB844757006',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'88.00',
  u'q': u'8',
  u'r': u'G3',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'1',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30615',
  u'd': u'995',
  u'e': u'0',
  u'f': u'0',
  u'g': u'0',
  u'h': u'07/19/15',
  u'i': u'VB793104621',
  u'ind': u'0',
  u'l': u'GA',
  u'n': u'Tickets will be ready for delivery by 07/19/2015.',
  u'p': u'91.00',
  u'q': u'8',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA',
  u'sd': u'0',
  u't': u'3',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'1',
  u'f': u'1',
  u'g': u'0',
  u'h': u'',
  u'i': u'VB844757008',
  u'ind': u'1',
  u'l': u'GA Main Floor',
  u'n': u'Instant Download.',
  u'p': u'111.00',
  u'q': u'8',
  u'r': u'G4',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'1',
  u'v': u'',
  u'z': u'0'},
 {u'c': u'30611',
  u'd': u'1000',
  u'e': u'0',
  u'f': u'0',
  u'g': u'0',
  u'h': u'07/16/15',
  u'i': u'VB791993584',
  u'ind': u'0',
  u'l': u'GA Main Floor',
  u'n': u'Zone Seating. The seller is committing to procure these tickets for you upon receipt of your order. After you place your order and your order is confirmed, we guarantee that your tickets will be within the listed zone or section listed or one comparable and that you will receive these tickets in time for the event or your money back. Orders exceeding four tickets may be split up into different rows within the requested zone or section.',
  u'p': u'170.00',
  u'q': u'6',
  u'r': u'GA',
  u'rhdn': u'0',
  u's': u'GA Main Floor',
  u'sd': u'0',
  u't': u'3',
  u'v': u'',
  u'z': u'1'}]

ticket_info 是从低价到高价的门票信息列表。现在只从上面的列表中提取price-infop 是对应票价的key。使用这些信息,它会给你这样的东西,

In [3]: price_list = [i.get('p') for i in ticket_info]

In [4]: price_list 
Out[4]: 
[u'27.00',
 u'29.00',
 u'30.00',
 u'37.00',
 u'39.00',
 u'46.00',
 u'50.00',
 u'53.00',
 u'53.00',
 u'57.00',
 u'61.00',
 u'85.00',
 u'94.00',
 u'88.00',
 u'91.00',
 u'111.00',
 u'170.00']

为了确保您将获得最低价格,您可以执行price_list.sort() 并获取其中的第一个元素。

【讨论】:

    猜你喜欢
    • 2015-05-25
    • 2013-04-01
    • 2015-04-02
    • 2016-10-08
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多