Beautifulsoup
Beautifulsop是一个python模块,该模块用于接收一个HTML或XML字符,然后将其进行格式化,之后便可以使用他提供的方式快速查找指定的元素(如图片,文字等),从而使得在html或xml中查找指定元素比起用正则表达式更简单。
所用库:
form bs4 import BeautifulSoup
常用方法及相关函数:
下面这篇文章对BeautifulSoup的讲解非常详细,推荐:
https://blog.csdn.net/kikaylee/article/details/56841789
Beautifulsoup使用举例:
这里使用Beautifulsoup爬取豆瓣图书的书名
先上代码:
from urllib import request
from bs4 import BeautifulSoup
def getHtmlCode(url):
headers = {
'User-Agent' : 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36'
}
url1 = request.Request(url, headers = headers)
page = request.urlopen(url1).read().decode()
return page
def getImg(page):
soup = BeautifulSoup(page,'html.parser') #按照html格式解析页面
book_list = soup.find(attrs={"id":"book"}) #找到id为book的标签,这是包含所有书名信息的最底层标签
book_list_name = book_list.find_all(attrs={"class":"title"}) #获取id为book标签下class为title的标签
for book_one in book_list_name:
print(book_one.string)
url = 'http://www.douban.com/tag/%E5%B0%8F%E8%AF%B4/?focus=book'
page = getHtmlCode(url)
getImg(page)
输出结果:
用浏览器查看豆瓣读书的首页:
可以看到,输出的就是豆瓣读书首页的所有书名。
代码讲解:
这里重点讲解Beautifulsoup的使用。
1.首先使用Beautifulsoup()把获取的网页源码交给Beautifulsoup处理。
soup = BeautifulSoup(page,'html.parser')
2. 我们打开浏览器查看网页源码,找到包含所有书名的最近的以及标签。
可以看到书名都保存在一个id = “book”的标签中,且该标签是包含所有书名最近的一层。
book_list = soup.find(attrs={"id":"book"})
该代码获取id = “book”标签的中的全部源码,保存在book_list中。
3. 想获得所有书名只获得book_list还够的,因为我们还需要知道书名保存的子标签,打开浏览器查看网页源码即可知。
可以看到书名是保存在id = “book”标签的子标签中,该子标签的class = “title”,根据这个来获得子标签的内容。这时有人会问了,为什么是根据class = “title”来定位到这个子标签呢?为什么不是根据target = “_blank”来定位呢?这个问题先放一放,等会儿再来解答。
book_list_name = book_list.find_all(attrs={"class":"title"})
获取到这些子标签。
for book_one in book_list_name:
print(book_one.string)
输出标签中的内容(.string是获取标签内容而不是标签属性)。
现在我们返回来思考上面提出问题,为什么不用target = “_blank”来定位到这些包含书名标签,其实答案很简单,就是唯一标识,class = “title”这个属性只有这些子标签包含,而target = “_blank”并不是唯一标识。
那么又问了,我是怎么知道class = “title”就是唯一标识,target = “_blank”不只有一种标签拥有呢?
答案是,我也不知道!准确的说是我一开始也不知道,我不可能通过查看网页源码来确定其他种类的标签(不包含书名的标签)是否也包含这个属性,这样做太花费时间和精力了,所以我是通过实验来确定的。
这里做个实验:把book_list_name = book_list.find_all(attrs={"class":"title"})换成book_list_name = book_list.find_all(attrs={"target":"_blank"})看会输出什么?
实验结果:
可以看到除了输出书名外还输出了None,为什么呢?可以猜测一下,应该是id = “book”标签下的子标签中除了含有书名的标签外,还有其他标签包含了target = “_blank”这个属性,但是这个标签中并没有内容,所以输出None。
查看浏览器源码,看看我们的猜测是否正确:
果然如此,说明我们的猜测是正确的,使用target = “_blank”这个属性定位标签会造成二义性。
如果觉得爬取书名太小儿科了,还想爬取书的所有图片保存在本地路径中,这里给出源码,有了上面的讲解,相信下面的代码读起来就不难了吧。
源码:(对上述源码稍加修改)
from urllib import request
from bs4 import BeautifulSoup
def getHtmlCode(url):
headers = {
'User-Agent' : 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36'
}
url1 = request.Request(url, headers = headers)
page = request.urlopen(url1).read().decode()
return page
def getImg(page):
soup = BeautifulSoup(page,'html.parser') #按照html格式解析页面
book_list = soup.find(attrs={"id":"book"}) #找到id为book的标签,这是包含所有书名信息的最底层标签
book_list_img = book_list.find_all('img')
x = 0
for book_one in book_list_img:
book_img_url = book_one.get('src')
print(book_img_url)
request.urlretrieve(book_img_url, 'E:\python_spider_fild\%s.jpg' %x)
x += 1
url = 'http://www.douban.com/tag/%E5%B0%8F%E8%AF%B4/?focus=book'
page = getHtmlCode(url)
getImg(page)
分析:
这里只需额外讲解一个方法:book_img_url = book_one.get('src')
该方法是获取book_one标签中的src属性的内容,src属性内容是对应图书的图片的url, 从浏览器中查看html源码可以看到:
结果:
图片下载到了本地路径下。