【问题标题】:Python Beautiful Soup Table Data Scraping all except a specific <td> dataPython Beautiful Soup Table Data 抓取除特定 <td> 数据之外的所有数据
【发布时间】:2019-04-02 21:39:55
【问题描述】:

我正在尝试从一个网站上抓取数据,该网站包含印度所有政治人物的数据,该网站以数字表示的多个页面。

url: http://www.myneta.info/ls2014/comparisonchart.php?constituency_id=1

我希望将数据从多个网站导出为 CSV 文件。

这是我正在尝试的示例表:

<tr>
    <td class=chartcell><a href='http://myneta.info/ls2014/candidate.php?candidate_id=7678' target=_blank>Banka Sahadev</a></td>
    <td class=chartcell align=center>53</td>
    <td class=chartcell align=center>M</td>
    <td class=chartcell align=center>IND</td>
    <td class=chartcell align=center><span style='font-size:150%;color:red'><b>Yes</b></span></td>
    <td class=chartcell align=center><span style='font-size:160%;'><b>1</b></span></td>
    <td class=chartcell align=center>1</td>
    <td class=chartcell align=left>     <b><span style='color:red'> criminal intimidation(506)</span></b>, <b><span style='color:red'> public nuisance in cases not otherwise provided for(290)</span></b>, <b><span style='color:red'> voluntarily causing hurt(323)</span></b>, </td>
    <td class=chartcell align=center>Graduate</td>
    <td class=chartcell align=center>19,000<br><span style='font-size:70%;color:brown'>~ 19&nbsp;Thou+</span></td>
    <td class=chartcell align=center>3,74,000<br><span style='font-size:70%;color:brown'>~ 3&nbsp;Lacs+</span></td>
    <td class=chartcell align=center>3,93,000<br><span style='font-size:70%;color:brown'>~ 3&nbsp;Lacs+</span></td>
    <td class=chartcell align=center>0<br><span style='font-size:70%;color:brown'>~ </span></td>
    <td class=chartcell align=center>N</td>
    <!--<td class=chartcell align=center>0<br><span style='font-size:70%;color:brown'>~ </span></td>
    <td class=chartcell align=center>0<br><span style='font-size:70%;color:brown'>~ </span></td>
    <td class=chartcell align=center>2,00,000<br><span style='font-size:70%;color:brown'>~ 2&nbsp;Lacs+</span></td> -->
</tr>

我使用 BeautifulSoup 来获取数据,但是如果我打开 CSV 数据,它们会以某种方式合并数据并且看起来非常笨拙。

这是我的代码:

num = 1

url ='http://www.myneta.info/ls2014/comparisonchart.php? 
constituency_id={}'.format(num)

headers= {'User-Agent': 'Mozilla/5.0'}

with open ('newstats.csv', 'w') as r:
r.write('POLITICIANS ALL\n')


while num < 3:
url ='http://www.myneta.info/ls2014/comparisonchart.php? 
constituency_id={}'.format(num)

time.sleep(1)
response = requests.get(url, headers)

if response.status_code == 200:
    soup = BeautifulSoup(response.content, 'html.parser')
    tablenew = soup.find_all('table', id = "table1")
    if len(tablenew) < 2:
        tablenew = tablenew[0]
        with open ('newstats.csv', 'a') as r:
            for row in tablenew.find_all('tr'):
                for cell in row.find_all('td'):
                    r.write(cell.text.ljust(250))
                r.write('\n')
    else: print('Too many tables')

else:
    print('No response')
    print(num)


num += 1

另外,我怎么能省略特定 td 中的数据? 就我而言,我不希望表格中的 IPC 详细信息的数据。

我对编码和 python 还很陌生。

【问题讨论】:

    标签: python web-scraping html-table beautifulsoup export-to-csv


    【解决方案1】:

    由于 PIC 详细信息列接缝始终是第七个,您可以将其切出:

    import csv
    import requests
    import time
    
    from bs4 import BeautifulSoup
    
    num = 1
    
    url ='http://www.myneta.info/ls2014/comparisonchart.php?constituency_id={}'.format(num)
    
    headers= {'User-Agent': 'Mozilla/5.0'}
    
    with open ('newstats.csv', 'w') as r:
        r.write('POLITICIANS ALL\n')
    
    while num < 3:
        url ='http://www.myneta.info/ls2014/comparisonchart.php?constituency_id={}'.format(num)
    
        time.sleep(1)
        response = requests.get(url, headers)
    
        if response.status_code == 200:
            soup = BeautifulSoup(response.content, 'html.parser')
            tablenew = soup.find_all('table', id = "table1")
            if len(tablenew) < 2:
                tablenew = tablenew[0]
                with open ('newstats.csv', 'a') as r:
                    for row in tablenew.find_all('tr'):
                        cells = list(map(lambda cell: cell.text, row.find_all('td')))
                        cells = cells[:7] + cells[8:]
                        writer = csv.writer(r, delimiter='\t')
                        writer.writerow(cells)
    
            else: print('Too many tables')
    
        else:
            print('No response')
            print(num)
    
    
        num += 1
    

    【讨论】:

      【解决方案2】:

      我认为“合并数据问题”是由于您实际上没有用逗号分隔单元格。在常规文本编辑器上检查 csv 生成的文件以查看。

      一个简单的解决方案是使用join 方法创建一个包含单元格列表的逗号分隔字符串,并将其打印到文件中。例如:

      content = [cell.text for cell in row.find_all('td')]
      r.write(';'.join(content)+'\n')
      

      在第一行,我使用了所谓的“列表理解”,它对您学习非常有用。这允许使用单行代码迭代列表中的所有元素,而不是执行“for”循环。在第二行,我对字符串; 使用join 方法。这意味着数组content 被转换为一个字符串,将所有元素与; 连接起来。最后我添加换行符。

      如果您想根据索引省略元素(比如说,省略第 7 列),我们可以使列表理解稍微复杂一点,如下所示:

      # Write on this array the indices of the columns you want
      # to exclude
      ommit_columns = [7]
      content = [cell.text
          for (index, cell) in enumerate(row.find_all('td'))
          if index not in ommit_columns]
      r.write(';'.join(content)+'\n')
      

      ommit_columns 中,您可以编写多个索引。在下面的列表推导中,我们使用enumerate 方法从row.find_all('td') 中获取所有索引和元素,然后过滤它们检查index 是否不在ommit_columnsarray 中。

      完整的代码应该是:

      from bs4 import BeautifulSoup
      import time
      import requests
      
      num = 1
      
      url ='http://www.myneta.info/ls2014/comparisonchart.php?constituency_id={}'.format(num)
      
      headers= {'User-Agent': 'Mozilla/5.0'}
      
      with open ('newstats.csv', 'w') as r:
          r.write('POLITICIANS ALL\n')
      
      
      while num < 3:
          url ='http://www.myneta.info/ls2014/comparisonchart.php?constituency_id={}'.format(num)
      
          time.sleep(1)
          response = requests.get(url, headers)
      
          if response.status_code == 200:
              soup = BeautifulSoup(response.content, 'html.parser')
              tablenew = soup.find_all('table', id = "table1")
              if len(tablenew) < 2:
                  tablenew = tablenew[0]
                  with open ('newstats.csv', 'a') as r:
                      for row in tablenew.find_all('tr'):
                          # content = [cell.text for cell in row.find_all('td')]
                          # r.write(';'.join(content)+'\n')
      
                          # Write on this array the indices of the columns you want
                          # to exclude
                          ommit_columns = [7]
                          content = [cell.text
                              for (index, cell) in enumerate(row.find_all('td'))
                              if index not in ommit_columns]
                          r.write(';'.join(content)+'\n')
              else: print('Too many tables')
      
          else:
              print('No response')
              print(num)
      
          num += 1
      

      响应会是这样的:

      POLITICIANS ALL
      
      Banka Sahadev;53;M;IND;Yes;1;1;Graduate;19,000~ 19 Thou+;3,74,000~ 3 Lacs+;3,93,000~ 3 Lacs+;0~ ;N
      Godam Nagesh;49;M;TRS;No;0;0;Post Graduate;31,39,857~ 31 Lacs+;72,39,000~ 72 Lacs+;1,03,78,857~ 1 Crore+;1,48,784~ 1 Lacs+;Y
      Mosali Chinnaiah;40;M;IND;No;0;0;12th Pass;1,67,000~ 1 Lacs+;30,00,000~ 30 Lacs+;31,67,000~ 31 Lacs+;40,000~ 40 Thou+;Y
      Naresh;37;M;INC;No;0;0;Doctorate;12,00,000~ 12 Lacs+;6,00,000~ 6 Lacs+;18,00,000~ 18 Lacs+;0~ ;Y
      Nethawath Ramdas;44;M;IND;No;0;0;Illiterate;0~ ;0~ ;0~ ;0~ ;N
      Pawar Krishna;33;M;IND;Yes;1;1;Post Graduate;0~ ;0~ ;0~ ;0~ ;N
      Ramesh Rathod;48;M;TDP;Yes;3;1;12th Pass;54,07,000~ 54 Lacs+;1,37,33,000~ 1 Crore+;1,91,40,000~ 1 Crore+;4,18,32,000~ 4 Crore+;Y
      Rathod Sadashiv;55;M;BSP;No;0;0;Graduate;80,000~ 80 Thou+;13,25,000~ 13 Lacs+;14,05,000~ 14 Lacs+;0~ ;Y
      

      【讨论】:

      • 嗨 Felipe,非常感谢您的知识。该答案帮助我从该链接中抓取数据。
      猜你喜欢
      • 2015-08-24
      • 1970-01-01
      • 2023-03-31
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 1970-01-01
      • 2015-03-20
      相关资源
      最近更新 更多