bsObj.findAll("table")[4].findAll("tr")[2].find("td").findAll("div")[1].find("a")
"Heavens! what a virulent attack!" replied the prince, not in the least disconcerted by this reception.
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
bsObj = BeautifulSoup(html)
nameList = bsObj.findAll("span", {"class":"green"})
for name in nameList:
print(name.get_text())
findAll(tag, attributes, recursive, text, limit, keywords)
find(tag, attributes, recursive, text, keywords)
前面已经介绍过——你可以传一个标签的名称或多个标签名称组成的 Python列表做标签参数。例如,下面的代码将返回一个包含 HTML 文档中所有标题标签的列表:
.findAll({"h1","h2","h3","h4","h5","h6"})
.findAll("span", {"class":{"green", "red"}})
nameList = bsObj.findAll(text="the prince")
print(len(nameList))
allText = bsObj.findAll(id="text")
print(allText[0].get_text())
bsObj.findAll(id="text")
bsObj.findAll("", {"id":"text"})
另外,用 keyword 偶尔会出现问题,尤其是在用 class 属性查找标签的时候,因为 class 是 Python 中受保护的关键字。也就是说,class 是 Python 语言的保留字,在 Python 程序里是不能当作变量或参数名使用的(和前面介绍的 BeautifulSoup.findAll() 里的 keyword 无关)。假如你运行下面的代码,Python 就会因为你误用 class 保留字而产生一个语法错误:
bsObj.findAll(class="green")
不过,你可以用 BeautifulSoup 提供的有点儿臃肿的方案,在 class 后面增加一个下划线:
bsObj.findAll(class_="green")
bsObj.findAll("", {"class":"green"})
看到这里,你已经见过 BeautifulSoup 库里的两种对象了。
bsObj.tag.subTag.anotherSubTag
这个 HTML 页面可以映射成一棵树(为了简洁,省略了一些标签),如下所示:
在后面几节内容里,我们仍然以这个 HTML 标签结构为例。
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for child in bsObj.find("table", {"id": "giftList"}).children:
print(child)
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for sibling in bsObj.find("table", {"id": "giftList"}).tr.next_siblings:
print(sibling)
让标签的选择更具体
bsObj.find("table",{"id":"giftList"}).tr
即使页面上只有一个表格(或其他目标标签),只用标签也很容易丢失细节。另外,页面布局总是不断变化的。一个标签这次是在表格中第一行的位置,没准儿哪天就在第二行或第三行了。如果想让你的爬虫更稳定,最好还是让标签的选择更加具体。如果有属性,就利用标签的属性
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
print(bsObj.find("img",{"src":"../img/gifts/img1.jpg"
}).parent.previous_sibling.get_text())
计算机科学里曾经有个笑话:“如果你有一个问题打算用正则表达式(regular expression) 来解决,那么就是两个问题了。”
aa*bbbbb(cc)*(d | )
把上面的规则连接起来,就获得了完整的正则表达式:
[A-Za-z0-9\._+]+@[A-Za-z]+\.(com|org|edu|net)
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
images = bsObj.findAll("img",{"src":re.compile("\.\.\/img\/gifts/img.*\.jpg")})
for image in images:
print(image["src"])
../img/gifts/img1.jpg
../img/gifts/img2.jpg
../img/gifts/img3.jpg
../img/gifts/img4.jpg
../img/gifts/img6.jpg
myTag.attrs
myImgTag.attrs["src"]
soup.findAll(lambda tag: len(tag.attrs) == 2)