Python Beautiful Soup Table Data Scraping все, кроме определенных <td>данных - PullRequest
0 голосов
/ 30 октября 2018

Я пытаюсь собрать данные с веб-сайта, который содержит данные всех политиков Индии с нескольких страниц, обозначенных цифрами.

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

Кроме того, как я могу опустить данные из конкретного тд? В моем случае мне не нужны данные подробностей IPC из таблицы.

Я довольно плохо знаком с программированием и питоном.

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Я думаю, что «проблема объединенных данных» связана с тем, что вы на самом деле не разделяете ячейки запятыми. Проверьте это сгенерированный CSV-файл в обычном текстовом редакторе, чтобы увидеть это.

Простым решением является использование метода join для создания единственной строки, разделенной запятыми, со списком ячеек и печати ее в файл. e.g.:

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_columns.

Полный код должен быть:

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
0 голосов
/ 30 октября 2018

Поскольку столбцы PIC Details выглядят всегда седьмыми, вы можете просто нарезать их:

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
...