如何逐行提取项目

时间:2017-08-19 16:57:03

标签: python beautifulsoup

我需要一些帮助,使用beautifulsoup4从我的广告资源网页中提取数据。

网页采用以下格式编写:项目名称,后面是列出该特定广告资源的多行详细信息的表格。

我有兴趣获取项目名称,实际数量和到期日期。

如果给出这样的HTML结构,我该如何去做呢(见附件)?

            <div style="font-weight: bold">Item X</div>
                <table cellspacing="0" cellpadding="0" class="table table-striped report-table" style="width: 800px">
                    <thead>
                        <tr>
                            <th>&nbsp;</th>
                            <th>Supplier</th>
                            <th>Packing</th>
                            <th>Default Qty</th>
                            <th>Expensive</th>
                            <th>Reorder Point</th>
                            <th>Actual Qty</th>
                            <th>Expiry Date</th>
                        </tr>
                    </thead>
                    <tbody>

                            <tr>
                                <td>1</td>
                                <td>Company 1</td>
                                <td>3.8 L</td>
                                <td>
                                    4
                                </td>
                                <td>
                                    No
                                </td>
                                <td>2130.00</td>
                                <td>350.00</td>
                                <td>31-05-2019</td>
                            </tr>

                            <tr>
                                <td>2</td>
                                <td>Company 1</td>
                                <td>3.8 L</td>
                                <td>
                                    4
                                </td>
                                <td>
                                    No
                                </td>
                                <td>2130.00</td>
                                <td>15200.00</td>
                                <td>31-05-2019</td>
                            </tr>

                            <tr>
                                <td>3</td>
                                <td>Company 1</td>
                                <td>3.8 L</td>
                                <td>
                                    4
                                </td>
                                <td>
                                    No
                                </td>
                                <td>2130.00</td>
                                <td>210.00</td>
                                <td>31-05-2019</td>
                            </tr>

                        <tr>
                            <td colspan="5">&nbsp;</td>
                            <td>Total Qty&nbsp;15760.00</td>
                            <td>&nbsp;</td>
                        </tr>
                    </tbody>
                </table>



            <div style="font-weight: bold">Item Y</div>
                <table cellspacing="0" cellpadding="0" class="table table-striped report-table" style="width: 800px">
                    <thead>
                        <tr>
                            <th>&nbsp;</th>
                            <th>Supplier</th>
                            <th>Packing</th>
                            <th>Default Qty</th>
                            <th>Expensive</th>
                            <th>Reorder Point</th>
                            <th>Actual Qty</th>
                            <th>Expiry Date</th>
                        </tr>
                    </thead>
                    <tbody>

                            <tr>
                                <td>1</td>
                                <td>Company 2</td>
                                <td>50X10&#39;s</td>
                                <td>
                                    10
                                </td>
                                <td>
                                    Yes
                                </td>
                                <td>1090.00</td>
                                <td>271.00</td>
                                <td>31-01-2020</td>
                            </tr>

                            <tr>
                                <td>2</td>
                                <td>Company 2</td>
                                <td>50X10&#39;s</td>
                                <td>
                                    10
                                </td>
                                <td>
                                    Yes
                                </td>
                                <td>1090.00</td>
                                <td>500.00</td>
                                <td>31-01-2020</td>
                            </tr>

                            <tr>
                                <td>3</td>
                                <td>Company 2</td>
                                <td>50X10&#39;s</td>
                                <td>
                                    10
                                </td>
                                <td>
                                    Yes
                                </td>
                                <td>1090.00</td>
                                <td>69.00</td>
                                <td>31-01-2020</td>
                            </tr>

                            <tr>
                                <td>4</td>
                                <td>Company 2</td>
                                <td>50X10&#39;s</td>
                                <td>
                                    10
                                </td>
                                <td>
                                    Yes
                                </td>
                                <td>1090.00</td>
                                <td>475.00</td>
                                <td>01-01-2020</td>
                            </tr>

                        <tr>
                            <td colspan="5">&nbsp;</td>
                            <td>Total Qty&nbsp;1315.00</td>
                            <td>&nbsp;</td>
                        </tr>
                    </tbody>
                </table>

3 个答案:

答案 0 :(得分:0)

一种解决方案是迭代每个行标记,即<tr>,然后只计算每个索引处的列单元格代表什么,并以这种方式访问​​列。为此,您可以使用BeautifulSoup中的find_all方法,该方法将返回包含给定标记的所有元素的列表。

示例:

from bs4 import BeautifulSoup
html_doc = YOUR HTML HERE
soup = BeautifulSoup(html_doc, 'html.parser')

for row in soup.find_all("tr"):
    cells = row.find_all("td")
    if len(cells) == 0:
        #This is the header row
    else:
        #If you want to access the text of the Default Quantity column for example
        default_qty = cells[3].text

请注意,如果tr标记实际上是标题行,则不会有td个标记(只会有th个标记),所以在这种情况下len(cells)==0

答案 1 :(得分:0)

这是一种方法。我们的想法是在div属性中使用bold子字符串迭代项目style元素。然后,对于每个项目,使用find_next_sibling()获取下一个table兄弟,并将行数据解析为字典,以便通过标题名称方便地访问:

from bs4 import BeautifulSoup


data = """your HTML here"""

soup = BeautifulSoup(data, "lxml")
for item in soup.select("div[style*=bold]"):
    item_name = item.get_text()
    table = item.find_next_sibling("table")

    headers = [th.get_text(strip=True) for th in table('th')]
    for row in table('tr')[1:-1]:
        row_data = dict(zip(headers, [td.get_text(strip=True) for td in row('td')]))

        print(item_name, row_data['Actual Qty'], row_data['Expiry Date'])
    print("-----")

打印:

Item X 350.00 31-05-2019
Item X 15200.00 31-05-2019
Item X 210.00 31-05-2019
-----
Item Y 271.00 31-01-2020
Item Y 500.00 31-01-2020
Item Y 69.00 31-01-2020
Item Y 475.00 01-01-2020
-----

答案 2 :(得分:0)

您可以选择所有divs并浏览以查找下一个table

如果查看除最后一行之外的表行,则可以从特定单元格中提取文本并构建库存清单。

soup = BeautifulSoup(markup, "html5lib")

inventory = []

for itemdiv in soup.select('div'):
    table = itemdiv.find_next('table')
    for supply_row in table.tbody.select('tr')[:-1]:
        sn, supplier, _, actual_qty, _, _, _, exp =  supply_row.select('td')

        item = map(lambda node: node.text.strip(), [sn, supplier, actual_qty, exp])
        item[1:1] = [itemdiv.text]
        inventory.append(item)

print(inventory)

您可以使用csv库来编写库存,如下所示:

import csv

with open('some.csv', 'wb') as f:
    writer = csv.writer(f,  delimiter="|")
    writer.writerow(('S/N', 'Item', 'Supplier', 'Actual Qty', 'Expiry Date'))
    writer.writerows(inventory)