BeautifulSoup 将 HTML 解析为 1 行字符串

BeautifulSoup Parses HTML as 1 Line String

出于某种原因,当我使用 beautifulsoup 解析 HTML 页面并将该页面打印到 txt 文件时,它会取消 html 的格式并将其放在 1 行.当我尝试使用正则表达式进行搜索时,它找到了一些东西然后打印出该行,但是这打印出了整个页面,因为它都是 1 行...我怎样才能让它停止这样做?

这是我的代码:

#!/usr/bin/python3

from bs4 import BeautifulSoup
import re
import urllib.request


def main():
    #Open the PID file and read the PID's
    URLList = []
    PID = [open("PID.txt").read().split()]
    for list in PID:
        for code in list:
            URLList.append("http://www.abb.com/productdetails/" + code)
    pageNo = 1
    for URL in URLList:
        fh = open("html.txt", "a")
        fh.write("\n\n\n\n\n")
        webPage = urllib.request.urlopen(URL)
        soup = BeautifulSoup(webPage.read())
        print("Page", pageNo, "retrieved")
        fh.write(str(soup.prettify().encode("utf-8")))
        pageNo += 1
    fh.close()
    output = open('html.txt', 'r')
    for line in output:
        line = line.rstrip()
        if re.search('NetDepth', line):
            print(line)


if __name__ == "__main__": main()

基本上,我需要它做的是打开 UPC's/PID's 的文件,然后转到他们所在的网站并打开他们的页面...这部分工作正常。然后我想 gt HTML 并将其全部放在一个 txt 文件中。从那里,我想在该文件中搜索某些元素,例如 div 标记或 ProductNetDepth id。问题是,当它找到其中之一时,它会打印整个文档,因为它认为它是一行。我只想要包含它的 HTML 行。

这里只是网站源代码的一部分:

        <div class="Dimensions pisEvenRow">

                                                                        <div id="ProductNetLength" class="detailPageLeftColumn">
                        Product Net Length:
                                  </div>

                    <div class="detailPageRightColumn">

                                    <div>68 mm</div>
                                                                                                  </div>
            </div>
        <div class="Dimensions pisOddRow">

                                                                        <div id="ProductNetDepth" title="Depth of a single unpacked product" class="detailPageLeftColumn">Product Net Depth:</div>

                    <div class="detailPageRightColumn">

                                    <div>67.5 mm</div>
                                                                                                  </div>
            </div>
        <div class="Dimensions pisEvenRowLast">

                                                                        <div id="ProductNetWeight" title="Weight of a single unpacked product" class="detailPageLeftColumn">Product Net Weight:</div>

                    <div class="detailPageRightColumn">

                                    <div>0.041 kg</div>
                                                                                                  </div>

这是从 beautifulsoup 写入文件后的样子:

ijQoI5DAFDwZHYnHo-npjlC99WMTQ6qWYJ8fkDP8ddGyBe9DZa4IVC3j3aFtg7m85t7V9lKauOCgTq5CZ7cJneFTTH12Nx8mLxeKkAmLee2awza0rGQucVII-WdAyptFtKvKDBSLWhBUFTU7WLzD7DN4tAZzUEbQDGL2VHY5A0&amp;t=635706797508895128"/>\xc2\xa0Loading Images..\r\n                </div>\n</div>\n</div>\n<div class="pisDetailPageTitle">General Information</div>\n<div class="pisOddRow">\n<div class="detailPageLeftColumn">\n<span>Extended Product Type:\r\n      </span>\n</div>\n<div class="detailPageRightColumn">\r\n                                  E213-25-001\r\n                  </div>\n</div>\n<div class="pisEvenRow">\n<div class="detailPageLeftColumn">\n<span>Product ID:\r\n      </span>\n</div>\n<div class="detailPageRightColumn">\r\n                                  2CCA703041R0001\r\n                  </div>\n</div>\n<div class="pisOddRow">\n<div class="detailPageLeftColumn">\n<span>EAN:\r\n      </span>\n</div>\n<div class="detailPageRightColumn">\r\n                                  7612270938711\r\n                  </div>\n</div>\n<div class="pisEvenRow">\n<div class="detailPageLeftColumn">\n<span>Catalog Description:\r\n      </span>\n</div>\n<div class="detailPageRightColumn">\r\n                                  E213-25-10 Change over switch 25A 1CO 250VAC\r\n                  </div>\n</div>\n<div class="pisOddRowLast">\n<div class="detailPageLeftColumn">\n<span>Long Description:\r\n      </span>\n</div>\n<div class="detailPageRightColumn">\r\n                                  Change over switches according DIN EN 60669-1, VDE 0632 Part 1, Rated currents: 16/25 A, 250 VACPDC, Contacts: 1 CO/2 CO, Module width: 0,5/1\r\n                  </div>\n</div>\n<div class="pisDetailPageTitle">\r\n      Categories\r\n      </div>\n<div class="pisEvenRowLast" id="pisEvenRowLast">\n<ul class="pisCategoryList">\n<span>Products</span><span class="CategorySeperator">\xc2\xbb</span>\n<li>                      Low Voltage Products and Systems\r\n                      </li>\n<span class="CategorySeperator">\xc2\xbb</span>\n<li>                      Modular DIN Rail Products\r\n                      </li>\n<span class="CategorySeperator">\xc2\xbb</span>\n<li>                      Modular DIN Rail Components MDRCs\r\n                      </li>\n<span class="CategorySeperator">\xc2\xbb</span>\n<li>                      Command Devices\r\n                      </li>\n</ul>\n</div>\n<div class="displayNone" id="PisDiv_PlaceHolder1">\xc2\xa0</div>\n<div class="pisDetailPageTitle" id="Ordering">Ordering</div>\n<div class="Ordering pisOddRow">\n<div class="detailPageLeftColumn" id="Ean">\r\n                            EAN:\r\n                                      </div>\n<div class="detailPageRightColumn">\n<div>7612270938711</div>\n</div>\n</div>\n<div class="Ordering pisEvenRow">\n<div class="detailPageLeftColumn" id="MinimumOrderQuantity">\r\n                            Minimum Order Quantity:\r\n                                      </div>\n<div class="detailPageRightColumn">\n<div>10 piece</div>\n</div>\n</div>\n<div class="Ordering pisOddRowLast">\n<div class="detailPageLeftColumn" id="CustomsTariffNumber">\r\n                            Customs Tariff Number:\r\n    

如果您能提供帮助,那就太好了...我已经尝试了从美化到尝试自己将其分成几行的所有方法,但似乎没有任何正确的方法。我希望它像源代码一样格式化,这样我就可以轻松地搜索并从中获取我需要的项目!感谢您的帮助,如果可以,请不要只给我一个答案,您能不能也解释一下您做了什么!

我试过这个简单的脚本来提取 NetDepth,它运行良好。

from bs4 import BeautifulSoup as bs
from urllib import urlopen

soup = bs(urlopen('<insert url here>').read())
print soup.find(id="ProductNetDepth").next_sibling.next_sibling.div.text

如果您查看 html 的结构,包含 mm 测量值的 div 是 ID 为 ProductNetDepth 的 div 的兄弟。所以我只是以此为基础。

如果你不熟悉soup的搜索功能,那你应该看看他们写的非常好documentation

此处针对您的问题有几种不同的可能解决方案,但我将演示最简单的一种。

首先,我将复习一下问题陈述和您的解决方案。

问题陈述: 打印包含特定短语(在本例中为 "NetDepth")的请求 HTML 页面的所有行。

尝试的解决方案: 您正在使用 urllib 请求 HTML 文件,然后尝试使用 BeautifulSoup 对其进行美化,将其写入文本文件,然后最后打开文本文件并使用正则表达式提取包含匹配正则表达式的特定行。

在我看来,这个解决方案对于我们在这里真正需要的东西有点笨拙。我们没有理由真的需要将 HTML 写入文件,然后再从文件中读取它。我们可以只处理 HTML 的内容,同时循环遍历 PID 并发出 HTTP 请求。此外,除了 "prettify",我们并没有真正使用 BeautifulSoup 的基本功能,即为特定标签解析 HTML(顺便说一句,它做得非常棒)。考虑到这两点,这里是建议的解决方案...

建议解决方案:使用requests获取HTML页面,逐行解析该页面内容,运行每行上的正则表达式以查找符合条件的行。

代码:

#!/usr/bin/python3
import re
import requests

def main():
    #Open the PID file and read the PID's
    URLList = []
    PID = [open("PID.txt").read().split()]
    for list in PID:
        for code in list:
            URLList.append("http://www.abb.com/productdetails/" + code)
    pageNo = 1

    for URL in URLList:
        response = requests.get(url=URL)

        for line in response.iter_lines():
            line = str(line.rstrip())
            if re.search('NetDepth', line):
                print(line)

记住PEP20、"Simple is better than complex"