HTML数据提取
这一片文章, 我们一起学习如何利用HTML标签来提取数据。
我们打开二手房网站:
我们打开开发者工具, 找到请求:
这次我们找的请求, 和以前的不一样了, 所以这里面带大家找一找, 以前我们找的请求都是json格式的响应数据, 那今天由于我们要学习如何提取html数据, 我们今天找的请求的响应就必须市html格式的数据。
我们找到数据以后, 将url, 请求头的user-agent全部找出来, 并写到代码里面去, 这个和以前操作是一样的。
url = 'https://cs.lianjia.com/ershoufang/rs/'
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36'
}
然后我们需要把这个请求里面的html格式的数据全部爬下来, 并且保存到一个文件当中:
import requests
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
"referer": "https://hip.lianjia.com/",
"cookie": "select_city=430100; lianjia_ssid=18717f43-a946-4e0f-a774-7965c8aa73ed; lianjia_uuid=0741e41c-75be-4e7b-9bd0-ee4002203371; sajssdk_2015_cross_new_user=1; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22192752ebbdd1116-0ed7d9ff3e4d3e-26001051-1474560-192752ebbded87%22%2C%22%24device_id%22%3A%22192752ebbdd1116-0ed7d9ff3e4d3e-26001051-1474560-192752ebbded87%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; _jzqckmp=1; _ga=GA1.2.1019355060.1728542865; _gid=GA1.2.344285568.1728542865; hip=vxXEKT3nj90U2y57pSYlx074hLYy_KITMLesLlcpGMh9Slf8YMXZvf6QAv4ZcLnkesWaYhh-nRlvZVlTmOjIT-Y-WHy-FZE7aLT3xJpXyb0QTDqy9NYovzxBro7rK3M3NlC9A0EE8fu1MXkSBUrVvLakvFPxaOW6Z1j6eke9A-aD546zbHzuKX3T4Q%3D%3D; Hm_lvt_46bf127ac9b856df503ec2dbf942b67e=1728542848,1728543853; Hm_lpvt_46bf127ac9b856df503ec2dbf942b67e=1728543853; HMACCOUNT=7AB3E94A75916BE3; _qzja=1.151913534.1728542860751.1728542860751.1728543853745.1728542860751.1728543853745.0.0.0.2.2; _qzjc=1; _qzjto=2.2.0; _jzqa=1.489454228011104260.1728542851.1728542851.1728543854.2; _jzqc=1; _jzqx=1.1728543854.1728543854.1.jzqsr=hip%2Elianjia%2Ecom|jzqct=/.-; srcid=eyJ0Ijoie1wiZGF0YVwiOlwiYmIwMmYyYzU1ODZjMjNhZGJjOGVmZTZmYmEyYzVlODQ0OGRkNGYxYjJjZjliZGY4MDZjMmExOTgwOThkYjVkMzFkOTEwOTc5NTliOGNlMzBmMWNhZGJiN2NhYTY3ZTE0OTQ3NDc2YTg4N2JmYTBiOTRhODJlMTZiYjdmY2UxMjdhMDljY2UxYTY0M2RhMTlhMzQyN2ZlYTc5MTFkZTdkMmY5NzQyZmRjMTRmYTRmNjk0NGNmYmM4ZjYzOTBlMjE4YThhYWQ2ZGUyZTRkZmE5ZjU2OGIxZmJmNzBiZGQzY2E5ZWEyYzEzZmY2ZTMyOTlkOGFkMDUzNDQ0NmNiZTVhZFwiLFwia2V5X2lkXCI6XCIxXCIsXCJzaWduXCI6XCI5YzhiMDQ2OVwifSIsInIiOiJodHRwczovL2NzLmxpYW5qaWEuY29tL2Vyc2hvdWZhbmcvcnMvIiwib3MiOiJ3ZWIiLCJ2IjoiMC4xIn0=; _jzqb=1.1.10.1728543854.1; _qzjb=1.1728542860751.2.0.0.0; _ga_4JBJY7Y7MX=GS1.2.1728542865.1.1.1728543871.0.0.0"
}
url = 'https://cs.lianjia.com/ershoufang/rs/'
res = requests.get(url,headers=headers)
print(res.text)
with open('链家.html','w',encoding='utf-8')as f:
f.write(res.text)
这里说明下, 后面有referer和cookie是为了防止被识别是爬虫程序, 博主在爬虫的过程中, 前面几次爬虫就是因为没有加referer和cookie, 结果没有把数据成功爬下来, 因为被网站视为是爬虫程序了。
运行代码后, 在代码的同级目录下, 会多出一个新的html文件。
打开文件:
我们发现就是我们找到的请求里面的响应内容, 我们给它爬下来并且将内容保存到了’链家.html’文件中。
我们需要用到html文件干什么呢?
我们需要用到html文件里面的html标签, 最终的目的是提取html标签里面的数据
那我们怎么提取数据呢?
这就是我们这篇文章要讲到的, 用xpath爬取数据, 在使用xpath之前, 我们需要安装lxml。
安装命令:
pip install lxml
lxml: 解析html的一个解析器, 用来提取html数据。
我们再使用xpath之前, 需要导入安装包:
from lxml import etree
然后使用etree的HTML函数, 参数传入的是html字符串, 为了解析html字符串文本的数据。
# 避免多次请求,提前将要解析的数据保存在了本地html文件中
# 提取数据,需要把文件中的字符串给读取出来
with open('链家.html','r',encoding='utf-8') as f:
html_code = f.read()
tree = etree.HTML(html_code)
我们刚才把请求html的数据并且保存到这个文件里面, 那我们需要读取刚才我们保存文件里面的数据, 用到with open(‘链家.html’,‘r’,encoding=‘utf-8’) as f这句话。将文件中获取到的数据, 进行html解析。
xpath用法:
一个杠(/):
tree.xpath('/html')
这个是为了获取html标签, 最左侧/:表示当前xpath表达式一定要从根标签开始定位。
print(tree.xpath('/html/head/title'))
非最左侧/:表示一个层级, 就是获取html标签中的head标签里面的title标签。
特点: 必须从跟标签开始定位, 最前面是/html
两个杠(//):
print(tree.xpath('//title'))
最左侧的//: 从html中的任意位置找标签, 不需要再从跟标签html开始了。
这段代码的意思是获取所有的title标签
print(tree.xpath('//div'))
获取所有的div标签
通过text()在我们获取到的标签里面的值(就是文本数据):
print(tree.xpath('//span/text()'))
获取标签的内容 获取网页中所有的span标签的文本内容。
两个杠相比于一个杠的用法来讲, 更加的灵活, 不过也有缺点, 就是一个网页, 会有很多相同的标签, 那我们到底要定位到哪个标签, 光靠我们讲的 / 和 // 肯定是不够的, 我们接下来要讲如何准确的定位到自己想要的标签。
如何准确的定位到自己想要的标签
那么想要解决上面所说的准确的定位的问题, 解决办法有两个:
第一钟方法:
通过父级标签来做限定, 使用这种方法的常用场景:目标标签没有任何的属性特征。
print(tree.xpath('//h2/span/text()'))
从当前网页中找h2标签的儿子span标签,获取span标签的文本内容, 此时, h2就是span的父级标签。
第二种方法:
利用属性来进行筛选以做到准确定位。就是说方我们看到网页有标签长这样:<标签名 属性名=属性值 > 文本内容 </标签名>, 我们就可以考虑使用属性名来定位了。
语法: 标签名[@属性名=“属性值”]
比如, 我们要获取这个a标签里面的文本:
<a class="" href="https://cs.lianjia.com/ershoufang/104113837527.html" target="_blank" data-log_index="1" data-el="ershoufang" data-housecode="104113837527" data-is_focus="" data-sl="">很安静的小高层,得房率高,全新精装修四居二卫</a>
我们可以这么写:
print(tree.xpath('//a[@href="https://cs.lianjia.com/ershoufang/104113837527.html"]/text()'))
我们再举个例子, 用第二种写法解决。
例子:获取网页中的div标签,并且div的标签身上必须要有data-price="16495"属性的儿子span标签的文本数据
代码:
print(tree.xpath('//div[@data-price="16495"]/span/text()'))
获取标签里面的属性值
语法: 标签/@属性名
比如, 我们要获取一个div的类名为info clear(class = info clear), div里面有个a标签, 获取a标签里面的href属性的值。
print(tree.xpath('//div[@class="info clear"]//a/@href'))
我们已经把xpath的内容讲完了, 那我们接下来就讲一个案例:
这个案例, 就是我们刚才打开过的二手房网站, 我们的这个案例就是利用xpath来爬取网站里面的数据, 要求爬取到标题和总价。
代码:
from lxml import etree
# 避免多次请求,提前将要解析的数据保存在了本地html文件中
# 提取数据,需要把文件中的字符串给读取出来
with open('链家.html','r',encoding='utf-8')as f:
html_code = f.read()
tree = etree.HTML(html_code)
lis = tree.xpath('//ul[@class="sellListContent"]/li') # 30个房屋信息的整体
for li in lis:
# 第一次循环 li=第一个房子信息的整体对象
# 第一次循环,li.xpath 通过编写的xpath语法 从当前第一个li标签中去匹配内容
# 配合.进行使用:代表当前标签
title = li.xpath('.//div[@class="title"]/a/text()')[0]
price = li.xpath('.//div[@class="totalPrice totalPrice2"]//text()')
# [' ', '220', '万'] ---》 220万
price = ''.join(price)
# 获取标题和总价
print(title, price)
思路, 我们可以先获取到大范围的标签, 确保我们要爬取的数据, 都在大标签的范围之内, 然后再依次去找我们要爬取的数据的小标签。
注意: .//div[@class=“title”]/a/text(), 最前面要加点号(.)
结果:
实战:
把剩下再框内的所有信息, 全部爬取。(依然还是用刚才的二手房网站)。
剩下还有房子信息, 房子单价, 大致地址。
我们总共有5个信息要爬, 分别是标题, 大致地址, 房子信息, 房子单价, 房子总价。
先自己尝试做一做哦, 不要马上看答案。
参考答案:
from lxml import etree
with open('链家.html', 'r', encoding='utf-8') as f:
html_code = f.read()
tree = etree.HTML(html_code)
info_ershoufang = tree.xpath('//div[@class="info clear"]')
print(info_ershoufang)
for i in info_ershoufang:
title = i.xpath('.//div[@class="title"]//text()')
print("标题:", ''.join(title))
address = i.xpath('.//div[@class="positionInfo"]//text()')
print("大致地址:", ''.join(address).replace(" ", ""))
house_info = i.xpath('.//div[@class="houseInfo"]//text()')
print("房子信息:", ''.join(house_info).replace("|", "、").replace(" ", ""))
unit_price = i.xpath('.//div[@class="unitPrice"]//text()')
print("房子单价:", ''.join(unit_price))
totalPrice = i.xpath('.//div[@class="totalPrice totalPrice2"]//text()')
print("房子总价:", ''.join(totalPrice).replace(" ", ""))
print()
你答对了吗? 如果答出来的话, 给自己一个掌声哦!!!👏
以上就是爬虫之html数据提取的所有内容了, 如果有哪里不懂的地方,可以把问题打在评论区, 欢迎大家在评论区交流!!!
如果我有写错的地方, 望大家指正, 也可以联系我, 让我们一起努力, 继续不断的进步.
学习是个漫长的过程, 需要我们不断的去学习并掌握消化知识点, 有不懂或概念模糊不理解的情况下,一定要赶紧的解决问题, 否则问题只会越来越多, 漏洞也就越老越大.
人生路漫漫, 白鹭常相伴!!!