附注:关于基础知识:
1.1最牛逼的库之一:BeautifulSoup4
我们此处使用一个网页作为例子:http://www.pythonscraping.com/pages/warandpeace.html。这是战争与和平的纯文本小说,其中所有的人名都使用绿色标记,对话内容使用红色标记。我们截取一种一段HTML代码,其中——
(此处为人名)
网络爬虫可以通过 class 属性的值,轻松地区分出两种不同的标签。例如,它们可以用BeautifulSoup 抓取网页上所有的红色文字,而绿色文字一个都不抓。以下给出代码。
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
bsObj = BeautifulSoup(html)
##建立了一个bs4对象
nameList = bsObj.findAll("span", {"class":"green"})
## namelist代表一个list 其中bs0bj的语法是findall(tagName, tagAttributes)前者是表情名,后者是类名
## 非常灵活,以后会继续使用findall
for name in nameList:
print(name.get_text())
##get_text会返回其中的文本值 如果直接读取name的话你会发现里面塞满了各种标签
1.2.1 BeautifulSoup的find()和findAll()
findAll(tag, attributes, recursive, text, limit, keywords)是其最基本的用法,但是后面几个基本没卵用。
1.2.2 beautifulsoup的对象们
1.2.3 导航树
findAll 函数通过标签的名称和属性来查找标签 。但是如果你需要通过标签在文档中的位置来查找标签, 这就是导航树(Navigating Trees)的作用。现在我们用虚拟的在线购物网站 http://www.pythonscraping.com/pages/page3.html 作为要抓取的示例网页。我随便看了看,发现复杂的一逼,其中有一百万(?)个标签,互相嵌套。每一个部分都是一个高级标签的孩子。一般情况下, BeautifulSoup 函数总是处理当前标签的后代标签。例如, bsObj.body.h1 选择了 body 标签后代里的第一个 h1 标签,不会去找 body 外面的标签。
在本次实例中,我们只需要爬取一部分子标签,这就是搜集类比表格的数据。这里不太懂。
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)
1.3 正则表达式
任意可以用一系列线性规则构成的字符串。正则表达式就是表达这组规则的缩写。这组规则的正则表达式如下所示
例如:[A-Za-z0-9\._+]+@[A-Za-z]+\.(com|org|edu|net)
A-Za-z0-9符号任选一个。+代表着匹配前面的字符 第一个是指必须有个字符 第二个是指字符可以乱七八糟混在一起但是必须有一个中括号里的东西。之后是转义字符代表一个.,再之后是com什么的。
1.4 正则表达式与bs4
在抓取网页的时候, BeautifulSoup 和正则表达式总是配合使用的。其实,大多数支持字符串参数的函数(比如, find(id="aTagIdHere"))都可以用正则表达式实现。比如想要抓取所有的图片文件,可以使用。这段代码会打印出图片的相对路径,都是以 ../img/gifts/img 开头,以 .jpg 结尾。
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")})
## 这里的正则表达式很有趣 src代表地址 之后re代表正则表达式的模块 通常写正则表达式都得这么写
## \.\.\/img\/gifts/img.*\.jpg"
for image in images:
print(image["src"])
1.5 Lambda表达式
Lambda 表达式本质上就是一个函数, 可以作为其他函数的变量使用;也就是说,一个函数不是定义成 f(x, y),而是定义成 f(g(x), y),或 f(g(x), h(x)) 的形式。
BeautifulSoup 允许我们把特定函数类型当作 findAll 函数的参数。唯一的限制条件是这些函数必须把一个标签作为参数且返回结果是布尔类型。 BeautifulSoup 用这个函数来评估它遇到的每个标签对象,最后把评估结果为“真”的标签保留,把其他标签剔除
soup.findAll(lambda tag: len(tag.attrs) == 2)这样会产生两个属性的标签。