Python程序设计 网页爬虫

27 篇文章 6 订阅

实验十三 网页爬虫

第1关:爬取网页的表格信息

湖南省统计局的湖南省第七次全国人口普查公报(第六号)网址如下: https://tjj.hunan.gov.cn/hntj/tjfx/tjgb/pcgbv/202105/t20210519_19079329.html

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

表格标签

爬取该页面的表格标签下的内容,存储在字符串 bg 中。

 

如何爬取网页数据

网络爬虫应用一般分为两个步骤:

(1)通过网络连接获取网页内容:

  1. requests

(2)对获得的网页内容进行处理:

  1. beautifulsoup4

在调用 requests.get(url) 函数后,返回的网页内容会保存为一个 response 对象,该对象的text 属性会返回所有的网页文本。

使用 BeautifulSoup() 可创建一个 BeautifulSoup 对象。BeautifulSoupfind(<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函数

通过 BeautifulSoupfind_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

网页如下:

注意:随着时间不同,网页的内容会变化

 

其对应的代码如下:

编写程序,爬取该页第一个讲座的时间、标题、主讲人和地点信息,存储在字符串 jzsjjzbtjzdd 中,如下所示:

 

分析该网页,可以观察到:

  • 每个讲座信息放在 classxinwen-wendiv 标签下;

  • 讲座时间包含在 classxinwen-sj-topdiv 标签下;

  • 讲座标题包含在 classxinwen-wen-btdiv 标签下;

  • 讲座主讲人地点包含在 classxinwen-sj-topdiv 标签下。

你需要掌握:如何爬取指定属性的 div 标签下的信息。

通过 BeautifulSoupfind() 方法,可以按照条件找到标签,返回标签的内容。

  1. find(name, attrs)
  • name : 按照 T 标签名字检索,名字用字符串形式表示,例如 div , li 。
  • attrs : 按照标签属性值检索,需要列出属性名称和值。
  1. xw=soup.find("div", class_="xinwen-wen")

可以返回 xinwen-wen 标签下的内容。

讲座div

在该内容下继续按照 classxinwen-wen-top 的条件使用 find,可以找到讲座时间的标签。

  1. jzsjbq=xw.find("div", class_="xinwen-wen-top")

讲座信息标签2

该标签的 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 函数

通过 BeautifulSoupfind_all(name,attr) 方法,可以找到符合条件的多个标签,将多个标签的内容返回为一个列表。

  1. lb=bg.find_all("div",class="xinwen-wen")

找到网页的所有 class 属性为 xinwen-wendiv 标签,存入列表 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()
  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值