这个库的使用常规是两行代码
from bs4 import BeautifulSoup
soup = BeautifulSoup("html","html.parser") #前面那个就是打开html界面,后面是解释器,这个自带的够用,也可以用别的
运行完了之后,这个soup应该就可以调取网页上的所有内容,把那个网页看成是用<body><p>,这些东西组成的网页,好理解多了,然后就可以用这个soup去调用这些body,p什么的。
soup.p.name #用.name的方式获得名字
soup.p.parent #获得父母标签
print(soup.prettify()) #prettify函数可以为网页的那一大批标签名字什么的增加换行符,每一个标签都分行显示,看起来更清晰。
pritn(soup.a.prettify()) #也可以单独对某一个标签做换行
requests+BeautifulSoup库实战:
1.定向爬虫就是只爬取一个url链接,扩展爬虫是从一个url扩展到更多的url,首先去了解定向爬虫。
2.request返回了r,r.text是网页的代码展示,<p><body>这一系列的东西,把这些东西用BeautifulSoup
3.用这么简单的办法从网页里面爬东西,那要求这东西就放在网页的代码里面,如果使用JavaScript动态生成的,那就没办法了。在网页上点右键,看网页源代码,然后搜一下文字在不在里面。
requests.get和BeautifulSoup处理的不同:
其实单从返回来看,差别不是很大,打印出来都是尖括号后面有一些乱码字符的样子。
BeautifulSoup库的使用方法是传入一段文档,然后返回文档里的对象。get得到的东西,虽然看着也是那么回事,可你没法调用啊,把它变成对象才能调用。
提取大学排名的步骤:
1.把网页信息爬下来
2.把信息存到合适的数据结构里
3.把数据结构展示出来
import requests
from bs4 import BeautifulSoup
import bs4
def GeTHTML(url):
try:
r = requests.get(url,timeout =30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def fillList(ulist,html):
soup = BeautifulSoup(html,"html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr,bs4.element.Tag):
tds = tr('td')
ulist.append([tds[0].string,tds[10].string,tds[2].string])
def printList(ulist,num):#python比较倾向于用format方法格式化输出
print("{:^10}\t{:^6}\t{:^10}".format("排名","学校名称","总分"))
for i in range(num):
u = ulist[i]
print("{:^10}\t{:^6}\t{:^10}".format(u[0],u[1],u[2]))
uinfo =[]
url = "http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html"
html = GeTHTML(url)
fillList(uinfo,html)
printList(uinfo,10)
1.soup的查找:
在soup=BeautifulSoup()之后,这里应该是数据结构上的变化,soup可以用title,name这些东西去检索了。
在源代码的文件里面,有什么东西,比如<title><p><a>,这些都可以直接用soup去索引,soup.a, soup,title , soup.p这样
这几个每一条返回的都是一行,如果页面里有很多的<a>,那用soup.a只返回第一个,要想把所有的都返回,就要用find_all语句
soup.find_all('a') #这个find_all就是用于全局查找的
如果要细致的需求
soup.find(id = "link1")
2.isinstance用来判断两个是否是同一个类型的
isisntance(A(),B) ,判断A和B是否是同一个类型
另外的就是type, type(A())==B
3.dict字典的使用:
(1)定义d={'a':1, 'b':2, 'c':3}
(2)调用d['a'] #调用dict的时候,跟数组的调用方法很类似,都是中括号,只不过里面不是1234,用的是字符的索引。
(3)>>>d >>>{'a':1, 'b':2, 'c':3} #如果输入d就把赋值的那一些给弹出来了
(4)d.pop('a') #删除用的是pop,输出被弹出的东西,然后删掉
dict根据key来计算value的存储位置,如果每次计算相同的key得出的结果不同,那dict内部就完全混乱了。这个通过key计算位置的算法称为哈希算法(Hash)
4.第二个函数里面的查找,顺序应该这样的,首先在源代码里面找清华大学,找到清华大学属于的那个<td>,然后找离这个最近的<tr>,一定要找到离要查对象最近的,也就是他的直属父亲。
BeautifulSoup返回对象存在的形式,是数组。tr下面,把那些尖括号,每一次尖括号直到这一次的结束,都变成了数组的一个元素。如果不是直属父亲,那遍历这个数组,在数组里面的子数组里面,肯定遍历不到。
输入print(tr('td'))
>>>[<td>298</td>, <td><div align="left">江西农业大学</div></td>, <td>江西省</td>]
tr('td')[0] >>><td>298</td>
上面代码里的.string,应该就是把这个<td>给跳过了,只输出里面的字符串部分,直接输出什么都出来了
5.输出print的格式化format
print("\t"),这个字符串的\t是Tab的意思
print("\n"),回车
format的格式化输出,格式是这样的:
print("{:^10} {:^10} {:^10}".format('a','b','c'))
format可以认为是一个插入结构,前面有一个字符串"xxxx".format(),format的括号里面写的就是原来print函数原来应该打印的。那个xxxx就是要对format括号里的东西做的处理。这里只学一个处理,{:^10},^是居中,<居左,>居右,后面就是一共占几位。
最后的排版问题
def printList(ulist,num):
tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
print(tplt.format("排名","学校名称","总分" , chr(12288)))
for i in range(num):
u = ulist[i]
print(tplt.format(u[0],u[1],u[2], chr(12288)))
把输出的这个函数给改掉
format那一行,之前和之后都改掉,之前的那一段由于上下,也就是第一行和下面所有行都用得上,所以单独拿出来做一个变量。
tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
括号里的第一个数字,是对应输出format后面的第几个元素,第二个^表示的是居中,这个^后面的10表示的是填充。
中英文输出的问题在于中英文的空格符号占的大小不一样,在中英文混合输出的时候,把空格改了就好很多