62499


下記のHTML構造を持つURLから、td要素のa,b,cを取得して１行に並ぶように以下scriptを作成したのですが、どうしてもdまで取得してしまい、且つ出力されるものが乱れてしまいます。  
div要素を限定するのかもしれませんが、理想とする出力を得る方法をご教示いただけないでしょうか。

■理想とする出力  
URLのタイトル（1）、a,b,c,a',b',c',a'',b'',c'',a''',b''',c''',a'''',b'''',c'''',a''''',b''''',c'''''  
URLのタイトル（2）、a,b,c,a',b',c',a'',b'',c'',a''',b''',c''',a'''',b'''',c'''',a''''',b''''',c'''''

* * *

**対象のHTML(例)**

[code]

    <div>
      <table width="100%" cellpadding="0" cellspacing="0">
        <tr>
          <th>
            <div>A</div><div>B</div>
          </th>
          <th>
            <div>C</div><div>D</div>
          </th>
          <th>
            E
          </th>
         </tr>
        <tr>
          <td>
            <div>a</div><div>b</div>
          </td>
          <td>
            <div><span><a id="123" href="xxx.html" class="yyy">c</a></span></div>
            <div>d</div>
          </td>
          <td>
            e
          </td>
        </tr>
        <tr>
          <td>
            <div>a'</div><div>b'</div>
          </td>
          <td>
            <div><span><a id="456" href="xxx.html" class="yyy">c'</a></span></div>
            <div>d'</div>
          </td>
          <td>
            e'
          </td>
        </tr>
      </table>
    </div>
    
[/code]

**スクリプト**

[code]

    import csv
    from urllib.request import urlopen
    from bs4 import BeautifulSoup
    import ssl
    ssl._create_default_https_context = ssl._create_unverified_context
    
    list = ["http://www.xxxxx", "http://www.xxxxxxxxxx"]
    
    for target_url in list:
        html = urlopen(target_url)
        bsObj = BeautifulSoup(html, "html.parser")
    
        # テーブルを指定
        try:
            title = bsObj.findAll("title")
            table = bsObj.findAll("table")[14] #ページ内で15番目のtable
            rows = table.findAll("tr")[1:6] # 1-5番目に記載しているものを取得
            # csvファイルに書き出す
            with open("ebooks_1.csv", "a", encoding='utf-8')  as file:
                writer = csv.writer(file)
                writer.writerow(title)
                csvRow = [] 
                for row in rows:
                    for cell in row.findAll('td')[:2]:
                        csvRow.append(cell.get_text())
                    writer.writerow(csvRow)
        except BaseException:
            with open("ebooks.csv", "a", encoding='utf-8')  as file:
                writer = csv.writer(file)
                writer.writerow(['エラー'])
    
[/code]


CC BY-SA 4.0
2020-01-23T12:10:29.307
62493
2020-01-23T19:36:51.040
2020-01-23T14:51:58.860
37403
question
python web-scraping beautifulsoup
webの要素をスクレイプする際のfindallの使い方


参考までに、`findall()` ではなく CSS selector を利用すると以下の様に書くことができます。

[code]

    bsObj = BeautifulSoup(html, "html.parser")
    csvRow = sum([
      [
        elm.getText() for elm in bsObj.select(
          f'table:nth-child(15) tr:nth-child({i}) td div'
        )[:3]
      ] for i in range(2, 6)
    ], [])
    
    print(csvRow)
    
    =>
    ['a', 'b', 'c', "a'", "b'", "c'"]
    
[/code]

※ CSS selector で使用されるインデックス番号は 1 から始まります(1-base index)


CC BY-SA 4.0
2020-01-23T19:36:51.040
62499
2020-01-23T19:36:51.040
62493
answer