第四讲:
今天我们来讲一下上期遗漏的问题,首先是讲述了基于bs4库的HTML内容查找的方法。
主要的一个方法是:
<>.find_all(name,attrs,recursive,string,**kwargs)
返回的是一个列表对象,存储的是查找的结果,
Name参数是对标签名的检索字符串
例如:
1 for link in soup.find_all('a'):
2
3 print(link.get('href'))
就是第三讲中的最后一个例子,soup.find_all(‘a’)
返回一个全HTML文档的所有的<a>标签的一个列表,然后通过for循环一一读取,最后输出所有的url连接,就这么简单。
Attrs参数是对标签属性值的检索字符串
Recursive是否都子孙全部检索,默认为True
String <>…</>中字符串区域的检索字符串
下面用Ipython来演示:
首先是name参数,返回的是所有<a>标签组成的一个列表。
接着是attrs参数,返回有atitle属性值的标签
剩下的就不一一详细介绍了,下面介绍两个等价:
<tag>(…) 等价于 <tag>.find_all(…)
soup(…) 等价于 soup.find_all(…)
还有一个方法是<>.find() 搜索且返回一个结果,同.find_all()参数。
下面我们进行一个实战练习,准备好IDE环境,一起来做吧。
这是票房网的一个数据,现在显示的是《后来的我们》票房最高,啧啧啧,我也想去看啊~~
哎,跑题了,我们的目标是把这个网页的数据给爬下来,然后绘制成我们自己写的一个二位表格。
主要是分为三步走:
① 获取票房排名的网页内容
② 提取网页内容中的信息到适合的数据结构
③ 利用数据结构展示并输出结果
为此我们编写了三个函数。
第一个,当然是我们的通用代码框架了。
1 '''通用代码框架'''
2
3 import requests
4
5
6
7 def getHTML_Text(url):
8
9 try:
10
11 r = requests.get(url,timeout = 20)
12
13 r.raise_for_status() #如果状态不是200,则产生异常
14
15 r.encoding = r.apparent_encoding
16
17 return r.text
18
19 except:
20
21 return '产生异常'
上述函数返回的是网页的内容,然后第二个是提取有用信息到我们的数据结构里面去。
首先我们从浏览器里面用审查元素功能,找到我们所需数据的位置,可以看到我们需要的信息都在<tr >的这个标签和他的子孙节点标签里面。
做一个数据结构,只要把采集到的数据放进里面就ok了。
电影名称name | 票房 Total_num | 人次 People | 场次 Play_num | 更新时间 Update_time |
直接看第二个函数:
1 import bs4
2
3 from bs4 import BeautifulSoup
4
5 def fillList(ulist,html):
6
7 soup = BeautifulSoup(html,'html.parser')
8
9 for tr in soup.find('tbody').children:
10
11 if isinstance(tr,bs4.element.Tag):
12
13 tds = tr('td')
14
15 ulist.append([tds[0]('a')[0].string,tds[1].string,
16
17 tds[2].string,tds[3].string,tds[4].string])
18
19
该函数有两个参数,第一个ulist是一个存储结果的列表对象,
第二个参数是html文本,就是我们第一个函数爬取得到的内容,然后我们用BeautifulSoup对其进行解析提取我们需要的信息。
然后通过一个.children产生的迭代器对象,对找到的<tr>标签的子孙节点进行一个迭代提取信息。看下图:
我们可以简单分析到:<tr>标签下面的都是<td>的子标签,而这些子标签的内容就是我们需要的信息,就可以用.string属性了。只是第一个<td>标签里面还有一个<a>标签,所以我们需要先查找到他的<a>标签,然后再用.string属性来提取信息。(tds[0]('a')[0].string)
最后看第三个函数:
1 def print_all_result(ulist):
2
3 print("{:16}\t{:8}\t{:8}\t{:8}\t{:20}"
4
5 .format('电影名称','票房','人次','场次','更新时间',chr(12288)))
6
7 for i in range(len(ulist)):
8
9 u = ulist[i]
10
11 print("{:16}\t{:8}\t{:8}\t{:8}\t{:20}"
12
13 .format(u[0],u[1],u[2],u[3],u[4],chr(12288)))
首先是设计一个表头,然后对存储了结果的列表对象进行迭代,就能打印出我们爬取到的信息了。
最后写一下main()函数:
1 def main():
2
3 url = 'http://58921.com/daily'
4
5 html = getHTML_Text(url)
6
7 result = []
8
9 fillList(result,html)
10
11 print_all_result(result)
大功告成!让我们来看看结果吧!
结果已经成功打印出来了,只是排版还有点小毛病,这个大家回去自己试着排版了,这里就不展示怎么排版了,毕竟这不是主要内容。
我们的重点是怎么分析我们要提取的信息,和怎么设计我们的数据结构,最后是编码,把我们的想法加以实现。
好了,本期到此结束,下期见。
本期全部代码:
1 import requests
2 import bs4
3 from bs4 import BeautifulSoup
4
5 def getHTML_Text(url):
6 try:
7 kv = {'User-Agent':'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12'}
8 r = requests.get(url,timeout = 20,headers = kv)
9 r.raise_for_status() #如果状态不是200,则产生异常
10 r.encoding = r.apparent_encoding
11 return r.text
12 except:
13 return '产生异常'
14
15 def fillList(ulist,html):
16 soup = BeautifulSoup(html,'html.parser')
17 for tr in soup.find('tbody').children:
18 if isinstance(tr,bs4.element.Tag):
19 tds = tr('td')
20 ulist.append([tds[0]('a')[0].string,tds[1].string,
21 tds[2].string,tds[3].string,tds[4].string])
22
23 def print_all_result(ulist):
24 print("{:16}\t{:8}\t{:8}\t{:8}\t{:20}"
25 .format('电影名称','票房','人次','场次','更新时间',chr(12288)))
26 for i in range(len(ulist)):
27 u = ulist[i]
28 print("{:16}\t{:8}\t{:8}\t{:8}\t{:20}"
29 .format(u[0],u[1],u[2],u[3],u[4],chr(12288)))
30
31 def main():
32 url = 'http://58921.com/daily'
33 html = getHTML_Text(url)
34 result = []
35 fillList(result,html)
36 print_all_result(result)
37
38 if __name__ == '__main__':
39 main()