92682


リストの取り扱いと、CSV出力について、どうも理解が出来ず困っております。

スクレイピング結果をCSVに書き出す学習をしておりますが、sample_02.pyのコードで、リストをCSVに書き出すことができません。

どの様にすれば、CSVに書き出すことができるかお教えください。

`writer.writerow([elem.text,
elem.get("href")])`の部分で、取得したテキストとリンクが格納されていると思いますが、`[elem.text,
elem.get("href")`は、カンマで結合？区切られているということになるのでしょうか？

[code]

    # sample_01.py
    
    import csv
    import requests
    from bs4 import BeautifulSoup
    
    url = "https://www.yahoo.co.jp/"
    res = requests.get(url)
    
    soup = BeautifulSoup(res.content, "html.parser")
    
    topics = soup.find(id = "Topics")
    
    # aタグのテキスト部分とhrefで取得したURLをCSV形式で書き出す
    with open("info_01.csv", "w", newline="", encoding="utf_8") as w:
        writer = csv.writer(w)
        for elem in topics.find_all("a"):
            writer.writerow([elem.text, elem.get("href")])
    
[/code]

実行結果（成功）

[code]

    臨時国会 法案成立率は95.5%NEW,https://news.yahoo.co.jp/pickup/6447265
    被害者救済法が成立,https://news.yahoo.co.jp/pickup/6447261
    来週は寒さ厳しく 西日本で雪恐れ,https://news.yahoo.co.jp/pickup/6447258
    
[/code]

次に、配列の取り扱いの学習のため、`elem.text`と`elem.get("href")`以下の様に、一旦、配列に格納し、`writerows`で一気に書き出す処理を行ってみましたが、うまくできません。

[code]

    # sample_02.py
    
    tag_li = []
    link_li = []
    with open("info-2.csv", "w", newline="", encoding="utf_8") as w:
        writer = csv.writer(w)
        for elem in topics.find_all("a"):
            tag_li.append(elem.text)
            link_li.append(elem.get("href"))
        
        writer.writerows([tag_li, link_li])
    
[/code]

実行結果（失敗 なぜ？？）

[code]

    臨時国会 法案成立率は95.5%NEW,被害者救済法が成立,来週は寒さ厳しく 西日本で雪恐れ,露、イランとドローン生産検討かNEW,工場で黄色いガス漏れ 付近に規制,奨学金650万円 返済終わりは50代,うるさい? 子連れ批判に医師訴えNEW,しらふのW杯 現地「意外に」好評NEW,かまくら出現12/10(土) 16:02共同通信,もっと見る,トピックス一覧
    https://news.yahoo.co.jp/pickup/6447265,https://news.yahoo.co.jp/pickup/6447261,https://news.yahoo.co.jp/pickup/6447258,https://news.yahoo.co.jp/pickup/6447256,https://news.yahoo.co.jp/pickup/6447263,https://news.yahoo.co.jp/pickup/6447249,https://news.yahoo.co.jp/pickup/6447264,https://news.yahoo.co.jp/pickup/6447259,https://news.yahoo.co.jp/articles/b58cff17ed19d2c0d5e64db996d0ebddc5f2d07a/images/000,https://news.yahoo.co.jp/topics/top-picks,https://news.yahoo.co.jp/topics
    
[/code]


CC BY-SA 4.0
2022-12-10T12:14:53.090
92680
2022-12-12T11:06:33.543
2022-12-10T16:36:41.307
3060
question
python python3 csv
python リストの取り扱いと、CSV出力について


簡単なプログラムを例に取ると

[code]

    import csv
    import io
    
    with io.StringIO() as fp:
        writer = csv.writer(fp)
    
        # writerow は１行分を書き込む
        writer.writerow(['1行目',110,120])
    
        # writerows は複数行を書き込む
        data = [['2行目',210,220],['3行目',310,320]]
        writer.writerows(data)
        res = fp.getvalue()
    
    print(res)
    # 1行目,110,120
    # 2行目,210,220
    # 3行目,310,320
    
[/code]

上記のような構造を持てばいいので

`writer.writerow([elem.text, elem.get("href")])`  
で１行分を書き込めているなら以下のように蓄えるだけです

[code]

    lines = []
    for elem in topics.find_all("a"):
        line = [elem.text, elem.get("href")]
        lines.append(line)
    
[/code]


CC BY-SA 4.0
2022-12-10T13:02:02.407
92682
2022-12-10T13:02:02.407
43025
92680
answer


> `writer.writerow([elem.text, elem.get("href")])`
> の部分で、取得したテキストとリンクが格納されていると思いますが、`[elem.text, elem.get("href")]`
> は、カンマで結合？区切られているということになるのでしょうか？

リストは要素を順番に保持しているだけで，要素をカンマで結合しているのは `csv.writer(w).writerow()` です。この部分を敢えて
`w.write()` で記述すると下記になります。

[code]

    w.write(','.join([elem.text, elem.get("href")]) + '\r\n')
    
[/code]

なお，RFC4180（CSVファイルの一般的書式）に従いデフォルトで付加される改行コードが `'\r\n'`（CRLF(0x0d,
0x0a)）のため，Windows の場合は（既に対応されていますが）`open()` の改行コードの自動変換（`'\n'` ->
`'\r\n'`）設定を無効（`newline=''` 有り）にする必要があります。  
または `csv.writer(w, lineterminator='\n').writerow()` で改行コードを `'\n'`（LF）に指定して
`open()` の改行コードの自動変換設定を有効（`newline=''` 無し）にする方法もあります。

一方，`writerows()` の一括書き込み方法は既に解決済みですが，念のため記述例を下記に示します。

[code]

    import csv
    import requests
    from bs4 import BeautifulSoup
    
    res = requests.get('https://www.yahoo.co.jp/', timeout=5)
    topics = BeautifulSoup(res.text, 'html.parser').find(id='Topics')
    
    lines = [[e.text, e.get('href')] for e in topics.find_all('a')]
    
    with open('info_02.csv', 'w', encoding='utf-8') as f:
        csv.writer(f, lineterminator='\n').writerows(lines)
    
[/code]


CC BY-SA 4.0
2022-12-12T10:58:39.693
92724
2022-12-12T11:06:33.543
2022-12-12T11:06:33.543
54588
54588
92680
answer