实验十三 网页爬虫
第1关:爬取网页的表格信息
湖南省统计局的湖南省第七次全国人口普查公报(第六号)网址如下: https://tjj.hunan.gov.cn/hntj/tjfx/tjgb/pcgbv/202105/t20210519_19079329.html

表格的内容存储在 <table></table> 标签中。

爬取该页面的表格标签下的内容,存储在字符串 bg 中。
如何爬取网页数据
网络爬虫应用一般分为两个步骤:
(1)通过网络连接获取网页内容:
requests
(2)对获得的网页内容进行处理:
beautifulsoup4
在调用 requests.get(url) 函数后,返回的网页内容会保存为一个 response 对象,该对象的text 属性会返回所有的网页文本。
使用 BeautifulSoup() 可创建一个 BeautifulSoup 对象。BeautifulSoup 的 find(<name>) 方法, name 为标签名。可在 HTML 文档中按照标签名返回标签内容 soup.find('table') 可返回 table 标签下的所有内容。
爬取网页 https://tjj.hunan.gov.cn/hntj/tjfx/tjgb/pcgbv/202105/t20210519_19079329.html , 将表格标签下的内容存储在字符串 bg 中。
import requests
from bs4 import BeautifulSoup
#代码开始
url = "https://tjj.hunan.gov.cn/hntj/tjfx/tjgb/pcgbv/202105/t20210519_19079329.html"
html = requests.get(url)
html.encoding = 'utf-8'
soup = BeautifulSoup(html.text,"html.parser")
bg = soup.find('table')
#代码结束
print(bg)
第2关:爬取表格中指定单元格的信息
本关任务:根据上个步骤中爬取的表格标签,将表格中从第四行的单元格的文本显示出来。

行标签和单元格标签
表格中每行的数据信息被封装在一个 <tr></tr> 之间的结构中。每列内容采用 <td></td> 表示。
因此,如果要获得其中的数据,需要首先找到 <tr></tr> 标签,并遍历其中每个 <td></td> 标签,获取其值。例如,表格的第四行对应的 html 代码如下:

find_all函数
通过 BeautifulSoup 的 find_all(name) 方法,可以找到多个标签,将多个标签的内容返回为一个列表 lb=bg.find_all("tr") 。找到表格的所有 tr 标签,存入列表 lb ,若需要找每行下的所有 td 标签,则需要对 lb 循环,对每个元素执行 find_all("td") 。
获取标签文本
在用 find() 方法找到特定的标签后,想获取里面的文本,可以用 .text 属性或者 .string 属性。
- 如果该标签下有多层次的子标签,则必须使用
text属性; - 对于该网页的
td标签,如上图所示,需要用text才能返回文本。并且需要用strip去掉换行符; - 如果使用最内层的
span标签,则可以使用string属性。
对于上述获得的表格标签的内容,爬取从第 4 行开始的文本,显示每行的地区名称、总人口、城镇人口、乡村人口和城镇化率。各项之间用空格隔开,包括最后一列后面也有空格每个地区换一行
import requests
from bs4 import BeautifulSoup
url = "https://tjj.hunan.gov.cn/hntj/tjfx/tjgb/pcgbv/202105/t20210519_19079329.html"
r=requests.get(url)
r.encoding = 'utf-8'
soup=BeautifulSoup(r.text,"html.parser")
bg=soup.find('table')
#代码开始
import re
tr1 = bg.find_all("tr")
lb = []
lb1 = []
for li in tr1:
lb.append(li.find_all("td"))
lb = lb[3:]
for k,i in enumerate(lb):
lb1.append([])
for j in i:
res = re.match(r'.*宋体\">(.*?)</span>',str(j),re.S)
lb1[k].append(res.group(1))
for i in lb1:
for j in i:
print(j,end=" ")
print()
#代码结束
第3关:将单元格的信息保存到列表并排序
本关任务:根据上个步骤中爬取的表格内容,将城市名称和人口数存放在列表 lb 中,按人口数降序排列后输出。

提示:存入列表时,只需要存入两列,需将人口数转换为数值型才能按照数值的降序排列,可以用 isnumeric 方法判断是否数字字符。
import requests
from bs4 import BeautifulSoup
url = "https://tjj.hunan.gov.cn/hntj/tjfx/tjgb/pcgbv/202105/t20210519_19079329.html"
r=requests.get(url)
r.encoding = 'utf-8'
soup=BeautifulSoup(r.text,"html.parser")
bg=soup.find('table')
lb=[]
#代码开始
import re
tr1 = bg.find_all("tr")
lb1 = []
for li in tr1:
lb1.append(li.find_all("td"))
lb1 = lb1[3:]
for k,i in enumerate(lb1):
lb.append([])
for j in i:
res = re.match(r'.*宋体\">(.*?)</span>',str(j),re.S)
if res.group(1).isnumeric():
lb[k].append(eval(res.group(1)))
else:
lb[k].append(res.group(1))
lb.sort(key=lambda x:x[1],reverse=True)
# #代码结束
for lbxx in lb:
print(lbxx[0],lbxx[1])
第4关:爬取 div 标签的信息
编写一个爬取湖南大学讲座信息网页的程序。
湖南大学讲座信息的网址为 https://www.hnu.edu.cn/xysh/xshd.htm 。
网页如下:
注意:随着时间不同,网页的内容会变化
其对应的代码如下:

编写程序,爬取该页第一个讲座的时间、标题、主讲人和地点信息,存储在字符串 jzsj 、jzbt 、jzdd 中,如下所示:
分析该网页,可以观察到:
-
每个讲座信息放在
class为xinwen-wen的div标签下; -
讲座时间包含在
class为xinwen-sj-top的div标签下; -
讲座标题包含在
class为xinwen-wen-bt的div标签下; -
讲座主讲人地点包含在
class为xinwen-sj-top的div标签下。

你需要掌握:如何爬取指定属性的 div 标签下的信息。
通过 BeautifulSoup 的 find() 方法,可以按照条件找到标签,返回标签的内容。
find(name, attrs)
name: 按照T标签名字检索,名字用字符串形式表示,例如div,li。attrs: 按照标签属性值检索,需要列出属性名称和值。
xw=soup.find("div", class_="xinwen-wen")
可以返回 xinwen-wen 标签下的内容。

在该内容下继续按照 class 为 xinwen-wen-top 的条件使用 find,可以找到讲座时间的标签。
jzsjbq=xw.find("div", class_="xinwen-wen-top")

该标签的 text 属性即为讲座时间。
注意:该文本中有空格和换行符,需要使用
strip去掉。
import requests
from bs4 import BeautifulSoup
url = 'https://www.hnu.edu.cn/xysh/xshd.htm'
r = requests.get(url)
r.encoding = 'utf-8'
#代码开始
soup = BeautifulSoup(r.text, "html.parser")
lb = soup.find_all("div", class_="xinwen-wen")
for i in lb:
jzsj = i.find("div", class_= "xinwen-sj-top").text.strip()
jzbt = i.find("div", class_= "xinwen-wen-bt").text.strip()
jzdd = i.find("div", class_= "xinwen-wen-zy").text.strip()
#代码结束
f1=open("jzxx.txt","w")
f1.write(jzsj+"\n")
f1.write(jzbt+"\n")
f1.write(jzdd+"\n")
f1.close()
第5关:爬取单页多个div标签的信息
改进上一关的代码。爬取湖南大学讲座网页的多个讲座信息,存储在二维列表 jzxx 中。
湖南大学讲座信息的网址为 https://www.hnu.edu.cn/xysh/xshd.htm 。
相关知识
1. find_all 函数
通过 BeautifulSoup 的 find_all(name,attr) 方法,可以找到符合条件的多个标签,将多个标签的内容返回为一个列表。
lb=bg.find_all("div",class="xinwen-wen")
找到网页的所有 class 属性为 xinwen-wen 的 div 标签,存入列表 lb 。
2. 列表的操作
对于得到的多个标签的列表,使用 for 循环,可以依次访问每个标签,使用 find 函数找出其时间、标题和地点的文本,加入到列表,再加入二维列表 jzxx 中。
爬取湖南大学讲座网页的多个讲座信息,存储在二维列表 jzxx 中。
import requests
from bs4 import BeautifulSoup
url = 'https://www.hnu.edu.cn/xysh/xshd.htm'
r = requests.get(url)
r.encoding = 'utf-8'
jzxx=[]
#代码开始
soup = BeautifulSoup(r.text, "html.parser")
lb = soup.find_all("div", class_="xinwen-wen")
for i in lb:
jzsj = i.find("div", class_= "xinwen-sj-top").text.strip()
jzbt = i.find("div", class_= "xinwen-wen-bt").text.strip()
jzdd = i.find("div", class_= "xinwen-wen-zy").text.strip()
jzxx.append([jzsj,jzbt,jzdd])
#代码结束
f1=open("jzxx2.txt","w")
for xx in jzxx:
f1.write(",".join(xx)+"\n")
f1.close()
第6关:爬取多个网页的多个div标签的信息
修改上关的程序,爬取从第 80 页到 85 页中的讲座信息,存放在 jz.txt 文件中每行显示一个讲座信息,讲座时间、讲座标题和主讲人地点用逗号分隔。
湖南大学讲座信息的第 80 页的网址为 https://www.hnu.edu.cn/xysh/xshd/80.htm 。


获取爬取多个网页
为了爬取多个网页,你需要通过循环产生多个不同 url 地址,再调用 requests 库的 get 方法,获得多个网页的 url 。
如何将信息写入文件
首先以 w 方式打开文件,再通过文件对象的 write 方法将字符串写入文件。
import requests
from bs4 import BeautifulSoup
f1=open("jz.txt","w",encoding="utf8")
#代码开始
for i in range(80,86,1):
respose = requests.get(f'https://www.hnu.edu.cn/xysh/xshd/{i}.htm')
respose.encoding = 'utf-8'
content = respose.text
soup = BeautifulSoup(content,'html.parser')
all_div = soup.findAll('div',class_='xinwen-wen')
for div in all_div:
jzsj = div.find('div',class_= 'xinwen-sj-top').string.strip()
jzbt = div.find('div',attrs={'class','xinwen-wen-bt'}).string.strip()
jzdd = div.find('div',attrs={'class','xinwen-wen-zy'}).text.strip()
f1.write(jzsj+','+jzbt+','+jzdd+'\n')
#代码结束
f1.close()


5867

被折叠的 条评论
为什么被折叠?



