質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

XPath(XML Path)

XML Path Language (XPath; XMLパス言語)は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文の事をいいます。XPathはXMLとは別の構文を使用します。XMLドキュメントの抽象、論理ストラクチャ上で動作します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Scrapy

Scrapyは、Pythonで開発されたオープンソースソフトウェアです。スクレイピングという、Webサービスから必要な情報を取り出したり自動操作をしたりする技術を使うものです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

2224閲覧

Python, Scrapyによる抽出結果CSVの行列を整列させたい

fukazume

総合スコア78

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

XPath(XML Path)

XML Path Language (XPath; XMLパス言語)は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文の事をいいます。XPathはXMLとは別の構文を使用します。XMLドキュメントの抽象、論理ストラクチャ上で動作します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Scrapy

Scrapyは、Pythonで開発されたオープンソースソフトウェアです。スクレイピングという、Webサービスから必要な情報を取り出したり自動操作をしたりする技術を使うものです。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2018/11/07 07:53

編集2018/11/08 12:25

###■質問
複数URLからの抽出結果を出力したCSVファイルの行列が、抽出する度に変化して不安定です。出力前にこの行列を安定させる(=整列させる)ことは可能でしょうか?

※なお各行のレベルでデータの整合性は問題ないです。
※以下イメージをご参照ください。

【CSV出力結果イメージ】
1回目
| date | time | name |
| page2のA1 | page2のB1 | page2のC1 |
| page2のA2 | page2のB2 | page2のC2 |
| page2のA3 | page2のB3 | page2のC3 |
| page1のA1 | page1のB1 | page1のC1 |
| page1のA2 | page1のB2 | page1のC2 |
| page1のA3 | page1のB3 | page1のC3 |

2回目
| name | date | time |
| page1のC1 | page1のA1 | page1のB1 |
| page1のC2 | page1のA2 | page1のB2 |
| page1のC3 | page1のA3 | page1のB3 |
| page2のC1 | page2のA1 | page2のB1 |
| page2のC2 | page2のA2 | page2のB2 |
| page2のC3 | page2のA3 | page2のB3 |

ScrapyCommand

1$ scrapy crawl example_spider -o test01.csv

PythonScrapySpider

1class ExampleSpider(scrapy.Spider): 2 name = 'example_spider' 3 allowed_domains = ['example.com'] 4 start_urls = [ 5 'https://example.com/page1.html', 6 'https://example.com/page2.html' 7 ] 8 9 def start_requests(self): 10 for url in self.start_urls: 11 yield SplashRequest(url, self.parse, 12 args={'wait': 0.5}, 13 ) 14 def parse(self, response): 15 table_rows = response.xpath('//table/tbody/tr') 16 for table_row in table_rows: 17 item = TutorialItem() 18 19 item['date'] = table_row.xpath('td[3]/a/text()').extract_first() 20 item['time'] = table_row.xpath('td[4]/a/text()').extract_first() 21 item['name'] = table_row.xpath('td[5]/a/text()').extract_first() 22 yield item

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

setting.pyに

FEED_EXPORTERS = { 'csv': 'your.custom.Exporter' }

と設定を書くと
your.custom.Exporter を利用してcsv出力できるようになりますので、
公式リファレンス を参考に自分でExporterを書くことで自由に挙動は変えられます。

例えば

your/custom.py

1from scrapy.exporters import CsvItemExporter 2 3 4class Exporter(CsvItemExporter): 5 def __init__(self, file, include_headers_line=True, join_multivalued=',', **kwargs): 6 super().__init__(file, include_headers_line, join_multivalued) 7 8 def start_exporting(self): 9 self.items = [] 10 11 def export_item(self, item): 12 self.items.append(item) 13 14 def finish_exporting(self): 15 # ここでself.itemsをソートする 16 # たとえば self.items.sort(key=lambda x: x["name"]) 17 18 if self.include_headers_line: 19 values = [x for x in self.items[0]] 20 self.csv_writer.writerow(values) 21 22 for item in self.items: 23 values = [item[x] for x in item] 24 self.csv_writer.writerow(values)

このように。

これは特にsort等はしていませんが
finish_exporting
にてitemsをsortしてさらにはitemをキーでsortすることで
出力を整形できるかと思います。

投稿2018/11/09 16:14

編集2018/11/15 07:51
calkinos

総合スコア452

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fukazume

2018/11/11 03:52 編集

ぬおぉぉ!返信が遅れまして誠に申し訳ございません。取り急ぎ御礼申し上げます!ちょっと時間を要すると思いますが頂いたアドバイスどおり動くよう初心者なりに挙動の検証にとりかかります。
fukazume

2018/11/14 10:03 編集

先日はご回答、誠にありがとうございました! 実はご提示いただいたコードをコピペし実行すると原因不明の"AttributeError"に悩まされていました。しかし昨日別件で、最新版のScrapy(それまで私のScrapyはPython2.7用でした。。)を導入したところ、この現象が解消しました。 しかしながら今回最新環境では、NameError: name 'items' is not defined と定義エラーが出るようになりました。そこで恐縮ながら追加質問なのですが: ①このエラーはソースコード内コメントの "itemsをsort" と何か関係はありますでしょうか? ②"def finish_exporting" でググってもstackoverflow等で、有益なソート方法のサンプルコードを見つけることができませんでした。どのようにfinish_exportingでアイテムをソートすればいいかヒントいただけますと大変ありがたいです。 ③ググっている中で、「pipelineでソート処理すべき」という旨のコメントをstackoverflow等で見かけましたが、Python開発ではExport時に高度な処理はせずプレーンなデータの出力により焦点を当て、pipelineなど、後のプロセスでデータ加工するというのが主流なのでしょうか。(ItemExporter関連のサンプルコード例自体をネット上であまり見かけなかったので自分は常識とは違う非効率なことをやっているのかなと若干感じましたので。pipelineはまだ概念しか理解できていないレベルですが。) 長文で申し訳ございません。
fukazume

2018/11/14 11:36

更新: "NameError: name 'items' is not defined" の件、self.items[0]とすることでエラー解消しました! 引き続き、②のサンプルコード、③のexport/pipelineとの役割分担に関しては、自分自身で解決できずにいますが。。
calkinos

2018/11/15 07:47

コードに一部ミスがあったようですみません。 ソートの方法としてはデータをどうみたいか?というところに依存するかと思います。 itemに含む値として今回は"date", "time","name"がありますのでそのうち値がユニークなものでソートするのが順番を固定する上では確実です。 ソートの方法は https://nwpct1.hatenablog.com/entry/python-lambda などが参考になると思います。 pipelineでも同じようなことはできますが、`scrapy crawl example_spider -o test01.csv`というようなコマンドでうまくいくのかはよくわかりません。 pipelineで行う場合はpipeline内で出力ファイルを開き、ソートしたデータを書き込むという作業を行うことになると思います。scrape実行時にファイル名を指定したい場合はたとえば`scrapy crawl example_spider -a output=test01.csv` などのように実行し、 spider側でpipelineにoutputで指定した値を渡すようにするなど、使用感としては異なるものになると予想しています。
fukazume

2018/11/15 08:18 編集

>コードに一部ミス いえいえ、とんでもございません。とても有益なアドバイスでした。 >ソートの方法は https://nwpct1.hatenablog.com/entry/python-lambda などが参考に 拝読した上で大変恥ずかしいのですが、ご提示頂いたソースコードのfinish_exporting部に具体的にどうこのlambda方式で記述するのか、理解に時間がかかりそうです。finish_exporting内のコードの各所にself.items.sort(key=lambda x: x["name"])を当てはめたりしていじくり倒しましたが、都度エラーが発生し期待したレコードをソートできませんでした。 もし可能であれば恐縮ですが、上記のコードで、例えば、"date", "time", の特定列だけを選択して出力するサンプルコードなどヒントを頂けるとありがたいのですが。 >spider側でpipelineにoutputで指定した値を渡すようにするなど、使用感としては異なるものになる わかりやすいご解説ありがとうございます。理解できました!
calkinos

2018/11/15 23:30

エラーが出る際はエラーメッセージ等を記載いただかないと何が起こっているのかはわかりかねますね。 特定列のみの出力は if 内の1行を values = ["date", "time"] に変更し for 内の1行を values = [item["date"], item["time"]] に変更すると "date"と"time" にすれば"date"と"time"の列だけ出力するようにできるかと思います。
fukazume

2018/11/16 03:14

エラーメッセージの件、様々試して都度エラーになるので、コメント欄の限られたスペースに中途半端に書くと断片的になり返って手がかりどころか混乱を招くと思ったので詳細を記載いたしませんでした。主に基本文法を知らない私の凡ミスによるエラーです。申し訳ございませんでした。 特定列の出力の件、正常に動作しました!大変、参考になりました。日にちを跨いできめ細やかにお教えくださいまして誠にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問