Python爬虫之数据解析

本文介绍了Python爬虫技术,通过正则表达式和BeautifulSoup库爬取并解析糗图百科的图片数据。同时,详细讲解了BS4和XPath解析原理及其实例应用,包括爬取三国演义章节标题和内容、58同城二手房源信息以及彼岸图网动漫图片。此外,还讨论了中文乱码的解决方法和XPath路径选取策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.图片数据爬取

**需求:**爬取糗图百科的一张图片

图片数据爬取代码:

import requests
if __name__ == '__main__':
	#如何爬取图片数据
	url = 'https://pic.qiushibaike.com/system/pictures/12462/124627742/medium/87WZPLC7TCXBL455.jpg'

	#content返回的是二进制形式的图片数据
	#text(字符串) content(二进制)json()(对象)
	img_data = requests.get(url = url,).content

	with open("D:/qiutu.jpg","wb") as fp:
		fp.write(img_data)
	<div class="thumb">

<a href="/article/124598970" target="_blank">
<img src="//pic.qiushibaike.com/system/pictures/12459/124598970/medium/G16Z94DSL6PR9128.jpg" alt="糗事#124598970" class="illustration" width="100%" height="auto">
</a>
</div>

2.Python爬虫之正则解析案例

爬取糗图百科页面的所有图片

代码:

import requests
import re
import os
#需求:爬取糗事百科中糗图模块下所有的糗图图片
if __name__ == '__main__':
	#创建一个文件夹,保存所有的图片
	if not os.path.exists('D:/糗图图片'):
		os.mkdir('D:/糗图图片')

	url = 'https://www.qiushibaike.com/imgrank/'
	headers={"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"}
	
	#使用通用爬虫对url对应的一整张页面进行爬取
	page_text = requests.get(url = url,headers= headers).text

	#使用聚焦爬虫将页面中的所有的糗图进行解析/提取
	ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
	img_src_list = re.findall(ex,page_text,re.S)  #re.S单行匹配   re.M多行匹配
	#print(img_src_list)
	for src in img_src_list:

		#拼接出一个完整的图片url
		src = 'https:'+src

		#请求到了图片的二进制数据
		img_data = requests.get(url = src,headers= headers).content

		#生成图片名称
		img_name = src.split('/')[-1]

		#图片存储的路径
		imgPath  = 'D:/糗图图片/'+img_name

		with open(imgPath,'wb') as f:
			f.write(img_data)
			print("------------"+img_name+"下载成功!!!------------")

爬取糗图百科所有页面的所有图片

代码:

import requests
import re
import os
#需求:爬取糗事百科中糗图模块下所有的糗图图片
if __name__ == '__main__':
	headers={"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"}
	
	#创建一个文件夹,保存所有的图片
	if not os.path.exists('D:/糗图图片'):
		os.mkdir('D:/糗图图片')

	#设置一个通用的Url模板
	url = 'https://www.qiushibaike.com/imgrank/page/%d/'
	for page_Num in range(1,13):
		new_url = format(url%page_Num)

		#使用通用爬虫对url对应的一整张页面进行爬取
		page_text = requests.get(url = new_url,headers= headers).text

		#使用聚焦爬虫将页面中的所有的糗图进行解析/提取
		ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
		img_src_list = re.findall(ex,page_text,re.S)  #re.S单行匹配   re.M多行匹配
		#print(img_src_list)
		for src in img_src_list:

			#拼接出一个完整的图片url
			src = 'https:'+src

			#请求到了图片的二进制数据
			img_data = requests.get(url = src,headers= headers).content

			#生成图片名称
			img_name = src.split('/')[-1]

			#图片存储的路径
			imgPath  = 'D:/糗图图片/'+img_name

			with open(imgPath,'wb') as f:
				f.write(img_data)
				print("------------"+img_name+"下载成功!!!------------")

3.bs4解析

数据解析的原理:

  • 1.标签定位
  • 2.提取标签、标签属性中存储的数据值

bs4数据解析的原理:

  • 1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
  • 2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取

如何实例化BesutifuiSoup对象:

  • from bs4 import BeautifulSoup
  • 对象的实例化:
    • 1.将本地的html文档中的数据加载到该对象中
      代码样例:
from bs4 import BeautifulSoup
if __name__ == '__main__':
	#将本地的html文档中的数据加载到该对象中
	fp = open('D:/text.html','r',encoding = 'utf-8')
	soup = BeautifulSoup(fp,'lxml')   # BeautifulSoup()有两个参数,其中一个必是'lxml'
	print(soup)
    · 2.将互联网上获取的页面源码加载到该对象中
	page_text = response.text
	soup = BeautifulSoup(page_text,'lxml')
  • 提供的用于数据解析的方法和属性:
  • 一 .soup.tagName : 返回的是文档中第一次出现的tagName对应的标签
 print(soup.a)  # soup.taoName 返回的是html中第一次出现的taoName标签
 print(soup.div)  #返回的是html中第一次出现的div标签
  • 二 .soup.find():
    1.find(‘tagName’):等同于soup.div
    2.属性定位:
    ----- soup.find(‘div’,class_/id/atter = ‘song)
    3.soup.find_all(‘tageName’):返回符合要求的所有标签(列表)
    4.select:
    ------ select(‘某种选择器(id,class,标签…选择器)‘),返回的是一个列表。
    ------ 层级选择器:
    --------- soup.select(’.tang > ul > li > a’ ) : >返回的是一个层级
    --------print(soup.select(’.tang > ul a’)[0]) : 空格表示的多个层级
    ------获取标签之间的文本数据:
    ---------soup.a.text/string/get_text()
    ---------text/get_text():可以获取某一个标签中所有的文本内容
    ---------string: 只可以获取该标签下面直系的文本内容
    ------获取标签中属性值:
    ---------soup.a[‘herf’]
    代码:
from bs4 import BeautifulSoup
if __name__ == '__main__':
	#将本地的html文档中的数据加载到该对象中
	fp = open('D:/text.html','r',encoding = 'utf-8')
	soup = BeautifulSoup(fp,'lxml')   # BeautifulSoup()有两个参数,其中一个必是'lxml'
	'''
	print(soup)   #输出的是整个fp文件的源代码内容
	print(soup.a)  # soup.taoName 返回的是html中第一次出现的taoName标签
	print(soup.div)  #返回的是html中第一次出现的div标签

	'''
	
	'''
	find('tageName'):等同于soup.div
	print(soup.find('div'))  #等价于print(soup.div)
	print(soup.find('div',class_= 'song'))  #定位到属性为class='song'的div中	
	
	'''

	#print(soup.find_all('a'))   #返回的是符合要求的所有标签(列表)

	#print(soup.selsect('.tang'))  #返回的是列表

	#print(soup.select('.tang > ul > li > a'  )[0])  #拿到的是第一个a标签
	#print(soup.select('.tang > ul a')[0])   #结果同上

	'''
	获取文本数据
	print(soup.select('.tang > ul a')[0].text)
	print(soup.select('.tang > ul a')[0].string)

	'''

	#print(soup.select('.tang > ul a')[0]['herf'])  #获取标签中属性值

bs4解析实例之爬取三国演义(内含出现乱码的解决方法)

代码:

import requests
from bs4 import BeautifulSoup

 #需求:爬取三国演义小说所有的章节标题和章节目录内容https://www.shicimingju.com/book/sanguoyanyi.html
if __name__ == '__main__':
       #对首页面数据进行爬取
       headers = {
 	      "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Edg/92.0.902.62",

       }
       url = 'https://www.shicimingju.com/book/sanguoyanyi.html'

       #出现乱码的解决方式1:
       page_text = requests.get(url = url,headers = headers)
       page_text.encoding='utf-8'
       page_text=page_text.text

       #在首页中解析出章节的标题和详情页的url
       #1.实例化BeautifulSoup对象,需要将页面源码数据加载到该对象中
       soup = BeautifulSoup(page_text,'lxml')

       fp = open('D:/sanguo.txt','w',encoding = 'utf-8')

       #解析章节标题和详情页的url
       li_list = soup.select('.book-mulu > ul > li')  #获取li列表
       for li in li_list:
 	      title = li.a.string
 	      detail_url = 'https://www.shicimingju.com' +li.a['href']

 	      #对详情页发起请求,解析出章节内容
 	      #出现乱码的解决方式2:
 	      detail_page_text = requests.get(url = detail_url, headers= headers)
 	      detail_page_text = bytes(detail_page_text.text,detail_page_text.encoding).decode('utf-8','ignore')

 	      #解析出详情页中相关的章节内容
 	      detail_soup = BeautifulSoup(detail_page_text,'lxml')
 	      div_tag = detail_soup.find('div',class_ = 'chapter_content')

 	      #解析到了章节内容
 	      content = div_tag.text
 	      fp.write(title+':'+content+'\n')
 	      print(title,'爬取成功')
 	      

4.xpath数据分析

xpath解析:

xpath解析:最常用且最便捷高效的一种解决方式、通用性

xpath解析原理:

1.实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中 ;
2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的捕获。

环境的安装:

pip install lxml

如何实例化一个etree对象:from lxml import etree

1.将本地的html文档中的源代码数据加载到etree对象中:
etree.parse(filePath)
2.可以将互联网上获取的源代码数据加载到该对象中
etree.HTML(‘page_text’)

xpath(‘xpath表达式’)

/ : 表示的是从根点开始定位,表示的是一个层级。
// :表示的是多个层级。可以表示从任意位置开始定位
属性定位: //div[@class=‘song’] tag[@attrName=“attrValue”]
索引定位://div[@class=“song”]/p[3] 索引时从1开始的。
取文本:

  1. /text() 获取的是标签中直系的文本内容
  2. //text() 标签中非直系的文本内容(所有文本内容)

取属性
/@atterName ==>img/src

代码:

from lxml import etree
if __name__ == '__main__':
	#实例化好了一个etree对象,且将被解析的源码加载到了该对象中
	tree = etree.parse('test.html')
	'''
	单行层级:
	r = tree.xpath('/html/head/title')  #因为是从根节点,所以html前面也需要加上一个/
	r = tree.xpath('/html/body/div')
	'''
	'''
	多层级
	r = tree.xpath('/html//div')  
	r = tree.xpath('//div')
	'''
	'''
	定位:
	r = tree.xpath('//div[@class="song"]')  #属性定位
	r = tree.xpath('//div[@class="song"]/p[3]')  #索引定位:索引时从1开始的,不是从0
	'''
	'''
	取文本
	r = tree.xpath('//div[@class="tang"]//li[5]/a/text()')[0]  #加text()是为了得到文本,而加[0]之前的文本是列表形式的,所以加了[0]为了只得到文本
	r = tree.xpath('//li[5]//text()')[0]  #加text()是为了得到文本,而加[0]之前的文本是列表形式的,所以加了[0]为了只得到文本
	r = tree.xpath('//div[@class="tang"]//text()') #得到的是div下面的所有文本内容,而换为/text()则无法得到 
	'''

	#r = tree.xpath('//div[@class="song"]img/@src')   #取属性的标签 
	print(r)

实例1—爬取58同城二手房源信息

终于弄出来了,昨天可能因为我长时间访问他们的网站,就导致我一直都爬取不了,今天终于爬取到了。如果你也爬取不了,你或许可以换一个User-Agent试试。

import requests
from lxml import etree
if __name__ == '__main__':
    url='https://bj.58.com/ershoufang/'
    headers={
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.78'
    }
    #获取整张数据
    page_text=requests.get(url=url,headers=headers).text
    #将得到的数据树化
    tree=etree.HTML(page_text)
    #获取整个数据
    div_list=tree.xpath('//section[@class="list"]/div')
    #创建文件
    fp=open('D:/58fangyuan.txt','w',encoding='utf-8')
    #获得数据中的标题
    for div in div_list:
        title = div.xpath('.//div[@class="property-content-title"]/h3/text()')[0]
        print(title)
        fp.write(title+'\n'+'.\n')


实列2—爬取彼岸图网的动漫图片

呜呜~~。要疯了,由于把ul写成了ur,无法成功爬取图片,便以为爬虫被发现了,就一直改,改了一下午,结果发现是一个字母写错了,郁闷死了。

网址链接:https://pic.netbian.com/.

代码:

#需求:解析下载图片数据
import requests
from lxml import etree
import os
if __name__ == '__main__':
	url = 'http://pic.netbian.com/4kdongman/'
	headers = {
		'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.78'
	}
	reponse = requests.get(url = url,headers = headers)
	#手动设定响应数据的编码格式
	#reponse.encoding = 'utf-8'
	page_text = reponse.text
        
	#创建文件夹
	if not os.path.exists('D:/动漫图片'):
		os.mkdir('D:/动漫图片')

	#数据分析:src的属性值  alt 属性
	tree = etree.HTML(page_text)
	li_list = tree.xpath('//div[@class="slist"]/ul/li')
	for li in li_list:
		img_src = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0]
		img_name = li.xpath('./a/img/@alt')[0]+'.jpg'

		#通用处理中文乱码的解决方案
		img_name = img_name.encode('iso-8859-1').decode('gbk')
		
		#请求图片进行持久化存储
		img_data = requests.get(url = img_src,headers= headers).content
		img_path= '动漫图片/'+img_name
		with open(img_path,'wb') as fp:
			fp.write(img_data)
			print(img_name,'下载成功!!!—————————————')

重要知识点一:
1.中文乱码的解决办法一:

	#手动设定响应数据的编码格式
	reponse = requests.get(url = url,headers = headers)
	#reponse.encoding = 'utf-8'
	page_text = reponse.text

2.中文乱码的解决办法二:

	#通用处理中文乱码的解决方案
	img_name = li.xpath('./a/img/@alt')[0]+'.jpg'
	img_name = img_name.encode('iso-8859-1').decode('gbk')

重要知识点二

路径节点的选取用法说明
/xpath(’/html’)从根节点选取html节点
//xpath(’//div’)从任意位置开始定位,匹配div节点
./xpath(’./div’)选取当前节点下的div

实例3—全国城市名称爬取

代码

import requests
from lxml import etree
#项目需求:解析出所有城市名称https://www.aqistudy.cn/historydata/
if __name__ == '__main__':
	headers = {
		'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.78'
	}
	url = 'https://www.aqistudy.cn/historydata/'
	page_text = requests.get(url=url,headers=headers).text

	tree = etree.HTML(page_text)
	host_li_list = tree.xpath('//div[@class="bottom"]/ul/li')
	all_city_names = []

	#解析到了热门城市的城市名称
	for li in host_li_list:
		host_city_name = li.xpath('./a/text()')[0]
		all_city_names.append(host_city_name)   #在列表末尾追加新的作用

	#解析全部城市
	city_names_list = tree.xpath('//div[@class="bottom"]/ul/div[2]/li')
	for li in city_names_list:
		city_name = li.xpath('./a/text()')[0]
		all_city_names.append(city_name)

	print(all_city_names,len(all_city_names))


简化版代码:

import requests
from lxml import etree
#项目需求:解析出所有城市名称https://www.aqistudy.cn/historydata/
if __name__ == '__main__':
	headers = {
		'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36 Edg/92.0.902.78'
	}
	url = 'https://www.aqistudy.cn/historydata/'
	page_text = requests.get(url=url,headers=headers).text

	tree = etree.HTML(page_text)
	
	#解析到热门城市和所有城市对应的a标签
	#//div[@class="bottom"]/ul/li   热门城市a标签的层级关系
	#//div[@class="bottom"]/ul/div[2]/li    全部城市a标签的层级关系
	a_list = tree.xpath('//div[@class="bottom"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
	all_city_names = []
	for a in a_list:
		city_name = a.xpath('./text()')[0]
		all_city_names.append(city_name)
	print(all_city_names,len(all_city_names))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值