使用漂亮的汤蟒进行刮痧

Posted

技术标签:

【中文标题】使用漂亮的汤蟒进行刮痧【英文标题】:Scraping using beautiful soup python 【发布时间】:2013-11-27 11:19:38 【问题描述】:
<div class="members_box_second">
                    <div class="members_box0">
                        <p>1</p>
                    </div>
                    <div class="members_box1">
                        <p class="clear"><b>Name:</b><span>Mr.Jagadhesan.S</span></p>
                        <p class="clear"><b>Designation:</b><span>Proprietor</span></p>
                        <p class="clear"><b>CODISSIA - Designation:</b><span>(Founder President, CODISSIA)</span></p>
                        <p class="clear"><b>Name of the Industry:</b><span>Govardhana Engineering Industries</span></p>
                        <p class="clear"><b>Specification:</b><span>LIFE</span></p>
                        <p class="clear"><b>Date of Admission:</b><span>19.12.1969</span></p>
                    </div>
                    <div class="members_box2">
                        <p>Ukkadam South</p>
                        <p class="clear"><b>Phone:</b><span>2320085, 2320067</span></p>
                        <p class="clear"><b>Email:</b><span><a href="mailto:jagadhesan@infognana.com">jagadhesan@infognana.com</a></span></p>                       
                    </div>
</div>
<div class="members_box">
                    <div class="members_box0">
                        <p>2</p>
                    </div>
                    <div class="members_box1">
                        <p class="clear"><b>Name:</b><span>Mr.Somasundaram.A</span></p>
                        <p class="clear"><b>Designation:</b><span>Proprietor</span></p>

                        <p class="clear"><b>Name of the Industry:</b><span>Everest Engineering Works</span></p>
                        <p class="clear"><b>Specification:</b><span>LIFE</span></p>
                        <p class="clear"><b>Date of Admission:</b><span>19.12.1969</span></p>
                    </div>
                    <div class="members_box2">
                        <p>Alagar Nivas, 284 NSR Road</p>
                        <p class="clear"><b>Phone:</b><span>2435674</span></p>      
                        <h4>Factory Address</h4>
                        Coimbatore - 641 027
                        <p class="clear"><b>Phone:</b><span>2435674</span></p>
                    </div>
</div>

我有上面的结构。从那我试图只刮掉class members_box1members_box2div 内的文本。

我有以下脚本,它只从 members_box1 获取数据

from bs4 import BeautifulSoup
import urllib2
import csv
import re
page = urllib2.urlopen("http://www.codissia.com/member/members-directory/?mode=paging&Keyword=&Type=&pg=1")
soup = BeautifulSoup(page.read())
for eachuniversity in soup.findAll('div','class':'members_box1'):
    data =  [re.sub('\s+', ' ', text).strip().encode('utf8') for text in eachuniversity.find_all(text=True) if text.strip()]
    print '\n'

这就是我尝试从两个盒子中获取数据的方式

from bs4 import BeautifulSoup
import urllib2
import csv
import re
page = urllib2.urlopen("http://www.codissia.com/member/members-directory/?mode=paging&Keyword=&Type=&pg=1")
soup = BeautifulSoup(page.read())
eachbox2 = soup.findAll('div ', 'class':'members_box2')
for eachuniversity in soup.findAll('div','class':'members_box1'):
    data =  eachbox2 + [re.sub('\s+', ' ', text).strip().encode('utf8') for text in eachuniversity.find_all(text=True) if text.strip()]
    print data

但我得到的结果与我仅获得 members_box1

的结果相同

更新

我希望输出像这样(单行)进行迭代

Name:,Mr.Srinivasan.N,Designation:,Proprietor,CODISSIA - Designation:,(Past President, CODISSIA),Name of the Industry:,Arian Soap Manufacturing Co,Specification:,LIFE,Date of Admission:,19.12.1969, "Parijaat" 26/1Shanker Mutt Road, Basavana Gudi,Phone:,2313861

但我得到如下

Name:,Mr.Srinivasan.N,Designation:,Proprietor,CODISSIA - Designation:,(Past President, CODISSIA),Name of the Industry:,Arian Soap Manufacturing Co,Specification:,LIFE,Date of Admission:,19.12.1969
"Parijaat" 26/1Shanker Mutt Road, Basavana Gudi,Phone:,2313861

【问题讨论】:

【参考方案1】:

您可以使用regex 匹配members_box1members_box2

import re
eachbox = soup.findAll('div', 'class':re.compile(r'members_box[12]'))
for eachuniversity in eachbox:

例如,

import bs4 as bs
import urllib2
import re
import csv

page = urllib2.urlopen("http://www.codissia.com/member/members-directory/?mode=paging&Keyword=&Type=&pg=1")
content = page.read()
soup = bs.BeautifulSoup(content)

with open('/tmp/ccc.csv', 'wb') as f:
    writer = csv.writer(f, delimiter=',', lineterminator='\n', )
    eachbox = soup.find_all('div', 'class':re.compile(r'members_box[12]'))
    for pair in zip(*[iter(eachbox)]*2):
        writer.writerow([text.strip() for item in pair for text in item.stripped_strings])

注意一定要把div后面的杂散空格去掉

soup.findAll('div ')

为了找到任何&lt;div&gt;标签。


上面的代码使用了非常方便的grouper idiom:

zip(*[iter(iterable)]*n)

此表达式从iterable 中收集n 项并将它们分组到一个元组中。因此,此表达式允许您迭代 n 项的块。我没有尝试解释how the grouper idiom works here。

【讨论】:

现在如何删除 [ ] 以及开头和结尾? 打印括号是因为data 是一个列表。如果您想打印data 的内容并用逗号连接在一起(例如),您可以使用print(', '.join(data))。 (我已经编辑了上面的代码来说明我的意思)。 它正在工作,但最后一件事。我希望每个 for 循环的数据都在一行中。 您的控制台或文本编辑器可能会将文本换成多行,但 Python 会为循环的每次迭代打印一行。 没有。我正在将它写入像这样的 csv 文件 python file.py &gt; ccc.csv 它分两行进行一次迭代【参考方案2】:

问题是您将eachbox2 添加到每个data,而不是添加到要循环的事物列表中。

除此之外,您还有一个杂散空间 'div ' 而不是 'div',这会导致 eachbox2 成为一个空列表。

试试这个:

eachbox1 = soup.findAll('div', 'class':'members_box1')
eachbox2 = soup.findAll('div', 'class':'members_box2')
for eachuniversity in eachbox1 + eachbox2:
    data =  [re.sub('\s+', ' ', text).strip().encode('utf8') for text in eachuniversity.find_all(text=True) if text.strip()]

这并不是最好的做事方式,它只是对您现有的做事方式最简单的解决方法。 BeautifulSoup 提供了多种不同的方法来在一个查询中搜索多个事物——例如,您可以基于值元组 ('members_box1', 'members_box2')、正则表达式 (re.compile(r'members_box[12]')) 或过滤函数 (lambda c: c in 'members_box1', 'members_box2') 进行搜索……

【讨论】:

当我尝试这个时,我实际上只看到了空白屏幕。!我不知道为什么 @Venky:可能是杂散空间?您的文档中没有 'div ' 标记...

以上是关于使用漂亮的汤蟒进行刮痧的主要内容,如果未能解决你的问题,请参考以下文章

用美丽的汤刮痧数据

在python中使用漂亮的汤和硒来解析html

findall 正则表达式字符串使用啥漂亮的汤?

使用 pip 安装漂亮的汤 [重复]

用漂亮的汤处理 xml 的编码错误

如何使用漂亮的汤和重新找到包含特定文本的特定类的跨度?