自己的笔记放在这里
入门试水
首先安装python库,要装两个 bs4 和html5lib,Windows下到CMD里面用pip装
pip install html5lib
pip install bs4
这里html5lib用来获取网页的HTML,而BS4(BeautifulSoup4)用来处理HTML,会把HTML按照里面的标签处理成一种树的分层结构,每个标签当作一个对象,然后按照标签的类和各种属性和来获取想要的内容。
像这种:
<div>
<a> </a>
<h1> </h1>
</div>
就可以理解成div对象里面包含d对象a和h1,类似于树的分支
BS4文档有中文的:
Beautiful Soup 4.4.0 文档beautifulsoup.readthedocs.io装的时候会读条
当然也可以手动安装
下面就import:
from bs4 import BeautifulSoup
import html5lib
import urllib.request
这里有坑其实,用的Python 和bs4 / html5lib的版本要对应, 不然import会出现:
No module named 'html5lib'
没问题的话就开搞,先抓取一个网页上面的HTML,写一个函数,传入URL,返回该网页的HTML:
def get_HTML(url):
response = urllib.request.urlopen(url)
html = response.read()
return html
然后就试一下效果
url="https://google.com.au"
html=get_HTML(url)
print(html)
成功了,但是还没有处理,所以出来的结果非常不友好:
下面就去找坦克世界吧,先找个帖子:
02-02【原创】8级金币车详解HT篇之四:最弱8级车FCM50t【坦克世界吧】_百度贴吧tieba.baidu.com打算把这个贴子的标题和每一层楼(层主、内容、时间、层数)取出来,先取标题,也就是“02-02【原创】8级金币车详解HT篇之四:最弱8级车FCM50”
这里先获取该页面的HTML并且用BeautifulSoup处理,返回soup:
def get_the_tiezi(url):
response = urllib.request.urlopen(url)
HTML = response.read()
soup = BeautifulSoup(HTML, "html.parser") # the html input and the parser name
然后要在这个HTML中取出标题,先回到页面上打开F12,找到标题Chrome的话,右键在标题上->检视
需要找到标题这个标签(h3)的唯一标识符,类似于数据库的PK,这里发现是它的class,值为“core_title_txt pull-left text-overflow”,写一个函数用来取标签:
def getTitle(soup):
title =soup.find( "h3",attrs={'class':'core_title_txt pull-left text-overflow'})
print("n",title.text)
soup.find()的作用是找出html第一个符合括号中的条件的标签,这里的
soup.find( "h3",attrs={'class':'core_title_txt pull-left text-overflow'})
意思为寻找出在soup中寻找class值为core_title_txt pull-left text-overflow的第一个h3标签。
注意,操作的时候发现soup.find()可以取出该soup标签下所有子标签,也就是根节点soup以下的所有结点都可以取到。
取完返回一个title,这里的title其实和soup一样,都是一个tag类的对象。HTML中所有的标签属性在这里变成了tag类的属性。也就是这里title.class==h3的class属性"core_title_txt pull-left text-overflow"
打印看效果:
下面取出帖子里面的每层楼,每一层楼都是一个独立的div,且class都等于“l_post l_post_bright j_l_post clearfix ”。每个楼层里面要取出四个:
先取出楼层
element = soup.findAll("div",attrs={'class':'l_post l_post_bright j_l_post clearfix'})
# the text that we are looking for
findAll()和find()的区别的是find()是取出第一个符合条件的,返回单个对象,而findAll()取出所有符合条件的tag,返回一个Arraylist<tag>
打印看看
肥肠乱
下面我们,对这个楼层list的内容循环,先取出作者(层主),手动加一个分割线:
for tag in element:
print("--------------------------------------------------------------------")
getAuthor(tag)
getAuthor就是取出当前楼层作者,需要先去F12找class属性:
def getAuthor(tag):
subauthor =tag.find( "a",attrs={'class':'p_author_name j_user_card'})
print("n",subauthor.text)
看一下效果:
下面同理取出内容:
def getContext(tag):
subcontext =tag.find( "div",attrs={'class':'d_post_content j_d_post_content'})
print("n",subcontext.text)
取时间和楼层的时候要注意,这里发现,网页中的HTML时间和楼层是完完全全一样的属性
所以这里用findAll():
def getLevel(tag):
sublevel =tag.findAll( "span",attrs={'class':'tail-info'})
print("n",sublevel[0].text)
def getDate(tag):
subtime =tag.findAll( "span",attrs={'class':'tail-info'})
print("n",subtime[1].text)
两个函数其实是取出同样的list,用下标来取第一个(楼层)和第二个(时间)。
把两个函数加进去,完成for loop:
for tag in element:
print("--------------------------------------------------------------------")
getAuthor(tag)
getContext(tag)
getLevel(tag)
getDate(tag)
看看效果:
结束!
等等,后面还发现每个帖子的URL都是:
https://tieba.baidu.com/p/4963823261
只有后面的4963823261不一样,修改这个ID就可以看其他的帖子了,于是乎
上交大这个博导被校方通报处理了,那个学生还能毕业吗【dota2吧】_百度贴吧tieba.baidu.com改一下ID看看: