最简单的爬虫
from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
print(html.read())
上述代码引入request模块,只导入一个urlopen函数,读取页面然后输出。
神器“BeautifulSoup”
BeautifulSoup库是python爬虫神器之一。通过定位HTML标签来格式化和组织复杂的的网络信息,用简单易用的python对象为我们展示XML结构信息。
安装BeautifulSoup
sudo apt-get install python-bs4
mac 系统
pip install beautifulsoup4
测试是否安装成功
$python
> from bs4 import BeautifulSoup
没有错误导入成功
运行BeautifulSoup
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read())
print(bsObj.h1)
输出 <h1>An Interesting Title</h1>
将html内容传入BeautifulSoup对象,然后通过对象提取h1标签。
复杂的html解析
BeautifulSoup的find()和findAll()函数将是我们最常用的函数。
findAll(tag, attributes, recursive, text, limit, keywords)
find(tag, attributes, recursive, text, keywords)
在大部分时间里我们只会使用前两个参数。
tag参数-传一个或者多个标签名称
.findAll({"h1","h2"})
attrubutes参数-用一个字典封装的若干属性和对应的属性值
.findAll("span",{"class":{"green","red"}})
其他参数请参照文档
BeautifulSoup对象
- BeautifulSoup对象
- 标签tag对象
- NavigableString对象
- Comment对象
BeautifulSoup导航树
1.处理子标签和其他后代标签
子标签室一个父标签的下一级,后代标签是指一个父标签下面所有级别的标签。一般情况下,beautifulsoup函数总是处理当前标签的后代标签。bsObj.div.findAll('img’)
会找出文档中的第一个div标签,获取这个div后代里所有的img标签列表。
只想找出子标签可以用.children标签
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)
2.处理兄弟标签
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)
这段代码会打印产品列表里的所有行的产品,第一行表格标题除外。对象不能把自己作为兄弟标签。任何时候你获取一个标签的兄弟标签,都不会包含这个标签本身。其次,这个函数只调用后面的兄弟标签。
3.父标签处理
在特殊情况下你也会用BeautifulSoup 的父标签查找函数,parent和parents。例如:
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())
这段代码会打印 ../img/gifts/img1.jpg 这个图片对应商品的价格(这个示例中价格是15.00)。
这是如何实现的呢?下面的图形是我们正在处理的 HTML页面的部分结构,用数字表示步骤的话:
<tr>
--<td>
--<td>
--<td>(3)
--"15.00" (4)
--<td>(2)
--<img src="./img/gifts/img1.jpg"> (1)
(1) 选择图片标签src=”../img/gifts/img1.jpg”;
(2) 选择图片标签的父标签(在示例中是
(3) 选择
(4) 选择标签中的文字,“$15.00”。
正则表达式
正则表达式和BeautifulSoup结合使用
Lambda表达式
下面的代码就是获取有两个属性的标签:
soup.findAll(lambdatag:len(tag.attrs) == 2)
这行代码会找出下面的标签:
<div class="body" id="content"></div>
<span style="color:red" class="title"></span>
如果你愿意,用lambda表达式选择标签将是正则表达式的完美替代方案。