根据SO,我写了一个spider,把每个域保存到一个单独的json文件中。我必须使用CrawlSpider
来访问子链接。
但是这个文件包含了json
的数据,不能被pandas
读取。它应该有一个很好的和可读的新行分隔的json。但是Scrapy希望导出的json是字节型的。
所需的输出格式为:
{"content": "text", "scrape_date": "36456456456"}
{"content": "text", "scrape_date": "56445435435"}
我的spider.py:
import scrapy
import time
import json
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy.crawler import CrawlerProcess
from urllib.parse import urlparse
DICT = {
'quotes.toscrape.com': 'domain1.json',
'stadt-koeln.de': 'domain2.json',
}
class PagingIncremental(CrawlSpider):
name = "my_spider"
allowed_domains = ['quotes.toscrape.com', 'stadt-koeln.de']
start_urls = [
'https://quotes.toscrape.com/page/1/',
'https://www.stadt-koeln.de/leben-in-koeln/planen-bauen/bebauungsplaene/aufstellen-eines-bauleitplanes'
]
custom_settings = {
'DOWNLOAD_DELAY': '0',
'FEED_EXPORT_ENCODING': 'utf-8',
'DEPTH_LIMIT': '1',
'AUTOTHROTTLE_ENABLED': 'True',
'AUTOTHROTTLE_START_DELAY': '1',
'AUTOTHROTTLE_MAX_DELAY': '3'
}
# Visit all found sublinks
rules = (
Rule(LinkExtractor(allow=r""), callback='parse', follow=False),
)
def parse(self, response):
item = {}
# get domain from each sub page
domain = urlparse(response.url).netloc
domain = domain.replace("www.", "")
# if domain from DICT above matches with domain from subpage
# all sublinks are stored in the same output file
item["filename"] = DICT[domain]
item["content"] = response.xpath("//p/text()").getall()
item['scrape_date'] = int(time.time())
yield item
if __name__ == "__main__":
process = CrawlerProcess(settings={
})
# process = CrawlerProcess()
process.crawl(PagingIncremental)
process.start()
我的pipelines.py
:
from scrapy.exporters import JsonItemExporter
class SaveJsonPipeline:
def process_item(self, item, spider):
filename = item['filename']
del item['filename']
# if the file exists it will append the data
JsonItemExporter(open(filename, "ab")).export_item(item)
return item
我的settings.py
:
ITEM_PIPELINES = {
'<project_name>.pipelines.SaveJsonPipeline': 300,
}
如果我使用a
而不是ab
以非二进制格式导出pipelines.py
中的数据,Scrapy会说:
JsonItemExporter(open(filename, "a")).export_item(item)
File "c:\python\lib\site-packages\scrapy\exporters.py", line 135, in export_item
self.file.write(to_bytes(data, self.encoding))
TypeError: write() argument must be str, not bytes
任何想法和解决方案都将获得奖励!
1条答案
按热度按时间sqyvllje1#
您应该使用JsonLinesItemExporter而不是
JsonItemExporter
来获取分隔行中的每个项目。不要麻烦
bytes
,因为文档提到它必须在bytes mode
中打开文件。在pandas.read_json()中,您可以使用选项
lines=True
来读取JSONL
(多行JSON):完整的工作代码。
所有代码都在一个文件中,因此每个人都可以简单地复制和测试它。
我使用
'__main__.SaveJsonPipeline'
从当前文件加载类。我还添加了代码来删除
content
中的空格,并加入一个字符串:第一个