.json 在 Scrapy 中导出格式
.json export formating in Scrapy
只是一个关于 json Scrapy 导出格式的快速问题。我导出的文件看起来像这样。
{"pages": {"title": "x", "text": "x", "tags": "x", "url": "x"}}
{"pages": {"title": "x", "text": "x", "tags": "x", "url": "x"}}
{"pages": {"title": "x", "text": "x", "tags": "x", "url": "x"}}
但我希望它采用这种格式。我需要以某种方式获取 "pages".
下的所有其他信息
{"pages": [
{"title": "x", "text": "x", "tags": "x", "url": "x"},
{"title": "x", "text": "x", "tags": "x", "url": "x"},
{"title": "x", "text": "x", "tags": "x", "url": "x"}
]}
我在 scrapy 或 python 方面不是很有经验,但除了导出格式外,我已经在我的蜘蛛中完成了所有其他工作。这是我的 pipelines.py,我刚开始工作。
from scrapy.exporters import JsonItemExporter
import json
class RautahakuPipeline(object):
def open_spider(self, spider):
self.file = open('items.json', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
这些是我的spider.py我需要提取的项目
items = []
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url):
item = TechbbsItem()
item['pages'] = {}
item['pages']['title'] = title
item['pages']['text'] = text
item['pages']['tags'] = tags
item['pages']['url'] = url
items.append(item)
return items
非常感谢任何帮助,因为这是我项目中的最后一个障碍。
编辑
items = {'pages':[{'title':title,'text':text,'tags':tags,'url':url}
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url)]}
这将以这种格式提取 .json
{"pages": [{"title": "x", "text": "x", "tags": "x", "url": "x"}]}
{"pages": [{"title": "x", "text": "x", "tags": "x", "url": "x"}]}
{"pages": [{"title": "x", "text": "x", "tags": "x", "url": "x"}]}
这越来越好,但我仍然只需要一个 "pages" 在文件的开头和它下面的数组中的所有其他内容。
编辑 2
我认为我的 spider.py 是 "pages" 被添加到 .json 文件中每一行的原因,我本来应该发布它的全部代码。在这里。
# -*- coding: utf-8 -*-
import scrapy
from urllib.parse import urljoin
class TechbbsItem(scrapy.Item):
pages = scrapy.Field()
title = scrapy.Field()
text= scrapy.Field()
tags= scrapy.Field()
url = scrapy.Field()
class TechbbsSpider(scrapy.Spider):
name = 'techbbs'
allowed_domains = ['bbs.io-tech.fi']
start_urls = ['https://bbs.io-tech.fi/forums/prosessorit-emolevyt-ja-muistit.73/?prefix_id=1' #This is a list page full of used pc-part listings
]
def parse(self, response): #This visits product links in the product list page
links = response.css('a.PreviewTooltip::attr(href)').extract()
for l in links:
url = response.urljoin(l)
yield scrapy.Request(url, callback=self.parse_product)
next_page_url = response.xpath('//a[contains(.,"Seuraava ")]/@href').extract_first()
if next_page_url:
next_page_url = response.urljoin(next_page_url)
yield scrapy.Request(url=next_page_url, callback=self.parse)
def parse_product(self, response): #This extracts data from inside the links
product_title = response.xpath('normalize-space(//h1/span/following-sibling::text())').extract()
product_text = response.xpath('//b[contains(.,"Hinta:")]/following-sibling::text()[1]').re('([0-9]+)')
tags = "tags" #This is just a placeholder
product_tags = tags
product_url = response.xpath('//html/head/link[7]/@href').extract()
items = []
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url):
item = TechbbsItem()
item['pages'] = {}
item['pages']['title'] = title
item['pages']['text'] = text
item['pages']['tags'] = tags
item['pages']['url'] = url
items.append(item)
return items
所以我的蜘蛛程序开始从充满产品列表的页面抓取。它访问了 50 个产品 link 中的每一个,并抓取了 4 个项目、标题、文本、标签和 url。在一页中抓取每个 link 后,它会转到下一页,依此类推。我怀疑代码中的循环阻止了你的建议对我有用。
我想将 .json 导出为原始问题中提到的确切形式。在文件的开头会有 {"pages": [
,然后是所有缩进的项目行
{"title": "x", "text": "x", "tags": "x", "url": "x"},
,最后是 ]}
items = {}
#item = TechbbsItem() # not sure what this is doing?
items['pages'] = []
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url):
temp_dict = {}
temp_dict['title'] = title
temp_dict['text'] = text
temp_dict['tags'] = tags
temp_dict['url'] = url
items["pages"].append(temp_dict)
return items
使用list comprehension。我不知道你的数据看起来如何,但使用玩具示例:
product_title = range(1,10)
product_text = range(10,20)
product_tags = range(20,30)
product_url = range(30,40)
item = {'pages':[{'title':title,'text':text,'tags':tags,'url':url}
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url)]}
我得到这个结果:
{'pages': [{'tags': 20, 'text': 10, 'title': 1, 'url': 30},
{'tags': 21, 'text': 11, 'title': 2, 'url': 31},
{'tags': 22, 'text': 12, 'title': 3, 'url': 32},
{'tags': 23, 'text': 13, 'title': 4, 'url': 33},
{'tags': 24, 'text': 14, 'title': 5, 'url': 34},
{'tags': 25, 'text': 15, 'title': 6, 'url': 35},
{'tags': 26, 'text': 16, 'title': 7, 'url': 36},
{'tags': 27, 'text': 17, 'title': 8, 'url': 37},
{'tags': 28, 'text': 18, 'title': 9, 'url': 38}]}
在内存使用方面,这不是一个好的做法,但一个选择是保留一个对象并在进程结束时写入它:
class RautahakuPipeline(object):
def open_spider(self, spider):
self.items = { "pages":[] }
self.file = null # open('items.json', 'w')
def close_spider(self, spider):
self.file = open('items.json', 'w')
self.file.write(json.dumps(self.items))
self.file.close()
def process_item(self, item, spider):
self.items["pages"].append(dict(item))
return item
然后,如果内存有问题(无论如何都要小心对待),请尝试按如下方式编写 json 文件:
class RautahakuPipeline(object):
def open_spider(self, spider):
self.file = open('items.json', 'w')
header='{"pages": ['
self.file.write(header)
def close_spider(self, spider):
footer=']}'
self.file.write(footer)
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
希望对您有所帮助。
只是一个关于 json Scrapy 导出格式的快速问题。我导出的文件看起来像这样。
{"pages": {"title": "x", "text": "x", "tags": "x", "url": "x"}}
{"pages": {"title": "x", "text": "x", "tags": "x", "url": "x"}}
{"pages": {"title": "x", "text": "x", "tags": "x", "url": "x"}}
但我希望它采用这种格式。我需要以某种方式获取 "pages".
下的所有其他信息{"pages": [
{"title": "x", "text": "x", "tags": "x", "url": "x"},
{"title": "x", "text": "x", "tags": "x", "url": "x"},
{"title": "x", "text": "x", "tags": "x", "url": "x"}
]}
我在 scrapy 或 python 方面不是很有经验,但除了导出格式外,我已经在我的蜘蛛中完成了所有其他工作。这是我的 pipelines.py,我刚开始工作。
from scrapy.exporters import JsonItemExporter
import json
class RautahakuPipeline(object):
def open_spider(self, spider):
self.file = open('items.json', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
这些是我的spider.py我需要提取的项目
items = []
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url):
item = TechbbsItem()
item['pages'] = {}
item['pages']['title'] = title
item['pages']['text'] = text
item['pages']['tags'] = tags
item['pages']['url'] = url
items.append(item)
return items
非常感谢任何帮助,因为这是我项目中的最后一个障碍。
编辑
items = {'pages':[{'title':title,'text':text,'tags':tags,'url':url}
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url)]}
这将以这种格式提取 .json
{"pages": [{"title": "x", "text": "x", "tags": "x", "url": "x"}]}
{"pages": [{"title": "x", "text": "x", "tags": "x", "url": "x"}]}
{"pages": [{"title": "x", "text": "x", "tags": "x", "url": "x"}]}
这越来越好,但我仍然只需要一个 "pages" 在文件的开头和它下面的数组中的所有其他内容。
编辑 2
我认为我的 spider.py 是 "pages" 被添加到 .json 文件中每一行的原因,我本来应该发布它的全部代码。在这里。
# -*- coding: utf-8 -*-
import scrapy
from urllib.parse import urljoin
class TechbbsItem(scrapy.Item):
pages = scrapy.Field()
title = scrapy.Field()
text= scrapy.Field()
tags= scrapy.Field()
url = scrapy.Field()
class TechbbsSpider(scrapy.Spider):
name = 'techbbs'
allowed_domains = ['bbs.io-tech.fi']
start_urls = ['https://bbs.io-tech.fi/forums/prosessorit-emolevyt-ja-muistit.73/?prefix_id=1' #This is a list page full of used pc-part listings
]
def parse(self, response): #This visits product links in the product list page
links = response.css('a.PreviewTooltip::attr(href)').extract()
for l in links:
url = response.urljoin(l)
yield scrapy.Request(url, callback=self.parse_product)
next_page_url = response.xpath('//a[contains(.,"Seuraava ")]/@href').extract_first()
if next_page_url:
next_page_url = response.urljoin(next_page_url)
yield scrapy.Request(url=next_page_url, callback=self.parse)
def parse_product(self, response): #This extracts data from inside the links
product_title = response.xpath('normalize-space(//h1/span/following-sibling::text())').extract()
product_text = response.xpath('//b[contains(.,"Hinta:")]/following-sibling::text()[1]').re('([0-9]+)')
tags = "tags" #This is just a placeholder
product_tags = tags
product_url = response.xpath('//html/head/link[7]/@href').extract()
items = []
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url):
item = TechbbsItem()
item['pages'] = {}
item['pages']['title'] = title
item['pages']['text'] = text
item['pages']['tags'] = tags
item['pages']['url'] = url
items.append(item)
return items
所以我的蜘蛛程序开始从充满产品列表的页面抓取。它访问了 50 个产品 link 中的每一个,并抓取了 4 个项目、标题、文本、标签和 url。在一页中抓取每个 link 后,它会转到下一页,依此类推。我怀疑代码中的循环阻止了你的建议对我有用。
我想将 .json 导出为原始问题中提到的确切形式。在文件的开头会有 {"pages": [
,然后是所有缩进的项目行
{"title": "x", "text": "x", "tags": "x", "url": "x"},
,最后是 ]}
items = {}
#item = TechbbsItem() # not sure what this is doing?
items['pages'] = []
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url):
temp_dict = {}
temp_dict['title'] = title
temp_dict['text'] = text
temp_dict['tags'] = tags
temp_dict['url'] = url
items["pages"].append(temp_dict)
return items
使用list comprehension。我不知道你的数据看起来如何,但使用玩具示例:
product_title = range(1,10)
product_text = range(10,20)
product_tags = range(20,30)
product_url = range(30,40)
item = {'pages':[{'title':title,'text':text,'tags':tags,'url':url}
for title, text, tags, url in zip(product_title, product_text, product_tags, product_url)]}
我得到这个结果:
{'pages': [{'tags': 20, 'text': 10, 'title': 1, 'url': 30},
{'tags': 21, 'text': 11, 'title': 2, 'url': 31},
{'tags': 22, 'text': 12, 'title': 3, 'url': 32},
{'tags': 23, 'text': 13, 'title': 4, 'url': 33},
{'tags': 24, 'text': 14, 'title': 5, 'url': 34},
{'tags': 25, 'text': 15, 'title': 6, 'url': 35},
{'tags': 26, 'text': 16, 'title': 7, 'url': 36},
{'tags': 27, 'text': 17, 'title': 8, 'url': 37},
{'tags': 28, 'text': 18, 'title': 9, 'url': 38}]}
在内存使用方面,这不是一个好的做法,但一个选择是保留一个对象并在进程结束时写入它:
class RautahakuPipeline(object):
def open_spider(self, spider):
self.items = { "pages":[] }
self.file = null # open('items.json', 'w')
def close_spider(self, spider):
self.file = open('items.json', 'w')
self.file.write(json.dumps(self.items))
self.file.close()
def process_item(self, item, spider):
self.items["pages"].append(dict(item))
return item
然后,如果内存有问题(无论如何都要小心对待),请尝试按如下方式编写 json 文件:
class RautahakuPipeline(object):
def open_spider(self, spider):
self.file = open('items.json', 'w')
header='{"pages": ['
self.file.write(header)
def close_spider(self, spider):
footer=']}'
self.file.write(footer)
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item)) + "\n"
self.file.write(line)
return item
希望对您有所帮助。