前言
??这系列的博客是我用来记录一些爬虫的小项目实例的,使用的抓包工具是request,数据解析工具是xpath,因为xpath相较于bs4和正则更加常用、便捷高效。下面就简单介绍一下xpath的原理和基本使用。
1 xpath原理
??首先是实例化一个etree的对象,且需要将被解析的页面源码加载到该对象中,这个页面源码可以已经下载在本地(etree.parse(filePath))也可以是从互联网上(etree.HTML(‘page_text’))获得的。其次调用etree对象中的方法结合xpath表达式实现标签的定位和内容的捕获。
2 xpath表达式
? “/” :最左侧的斜杆表示从根节点开始遍历。处于中间位置表示一个层级。 ? “//”:表示多个层级。相当于bs4中的">>"。 ? 标签定位://div[@class=“属性名”],要注意的是标签索引定位是从1开始。 ? 取文本:/text()获取的标签的直系文本内容,//text()获取该标签下的所有文本内容。 ? 取属性:/@属性名
3 北京58同城二手房信息爬取
网址信息为https://bj.58.com/ershoufang/,打开之后页面如下: 导入相关包
import requests
import pandas as pd
from lxml import etree
进行UA伪装,这是十分必须的,因为程序爬虫可能会被网页认为是非法的,所以我们要把程序伪装成浏览器。因此我们要向网页提供系统信息。这个参数可以在网页源码中获取。
headers = {
'User-Agent' : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36"
}
发送一个get请求并获得整个页面响应数据的源码,然后进行局部信息爬取。
url = "https://bj.58.com/ershoufang/"
page_text = requests.get(url = url, headers = headers).text
创建etree实例对象,这里我定义页面编码格式为utf-8,是为了防止一些不是正规的utf-8编码格式的源码而报错。
parse = etree.HTMLParser(encoding='utf-8')
tree = etree.HTML(page_text, parser = parse)
局部标签定位,本次房价信息的获取包括标题、房型、面积、朝向、楼层、建造时间、每平方价格、总价以及地址。 我们的步骤是先定位到相关文本数据所在标签,然后运用 /text() 或者 //text() 函数进行文本获取。在检查网页源码之后,发现所有的文本数据均在属性值为 "list" 的 select 的直系 div 标签中,且类属性值为 "property" ,因此可以先获得 select 下的所有 div 标签。
div_list = tree.xpath('//section[@ class = "list"]/div[@ class = "property"]')
然后再检查具体信息的标签所在位置,如标题在 div 的直系标签 a 下的第二个直系 div 标签中,且最终位于 h3 标签的 title 属性中。
title.append(div.xpath('./a/div[2]//h3/@title')[0])
其他数据的获取大同小异,只是在数据的处理上有些不同,比如得到房价的文本数据是有 ’\n’ 和空格的,要运用字符串的相关函数进行删除。最后就是数据的持久化存储,这里我把房价信息保存为csv文件。
df = pd.DataFrame({"标题" : title, "房型" : fangxing, "面积" : area, "朝向" : chaoxiang, "楼层" : louceng
, "建造时间" : time, "每平方米/万元" : one_price, "总房价" : total_price, "地址" : address})
df.to_csv("58同城房价.csv", encoding = "utf-8", index = True, index_label = "序号")
结果: 完整代码:
import requests
import pandas as pd
from lxml import etree
if __name__ == "__main__" :
headers = {
'User-Agent' : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.81 Safari/537.36"
}
url = "https://bj.58.com/ershoufang/"
page_text = requests.get(url = url, headers = headers).text
parse = etree.HTMLParser(encoding='utf-8')
tree = etree.HTML(page_text, parser = parse)
div_list = tree.xpath('//section[@ class = "list"]/div[@ class = "property"]')
title, fangxing, area, chaoxiang, louceng, time, total_price, one_price, address = [], [], [], [], [], [], [], [], []
for div in div_list :
title.append(div.xpath('./a/div[2]//h3/@title')[0])
fangxing_temp = div.xpath('./a//div[@ class = "property-content-info"]/p[1]//text()')
s = ""
for str in fangxing_temp :
if str != ' ' :
s += str
fangxing.append(s)
area_temp = div.xpath('./a//div[@ class = "property-content-info"]/p[2]/text()')
s = area_temp[0].strip(' \n')
area.append(s)
chaoxiang.append(div.xpath('./a//div[@ class = "property-content-info"]/p[3]/text()')[0])
louceng.append(div.xpath('./a//div[@ class = "property-content-info"]/p[4]/text()')[0].strip(' \n'))
time.append(div.xpath('./a//div[@ class = "property-content-info"]/p[5]/text()')[0].strip(' \n'))
total_price.append(div.xpath('./a//div[@ class = "property-price"]/p[1]//text()')[0] + '万')
one_price.append(div.xpath('./a//div[@ class = "property-price"]/p[2]//text()')[0])
address.append('-'.join(div.xpath('./a//section/div[2]/p[2]//text()')))
df = pd.DataFrame({"标题" : title, "房型" : fangxing, "面积" : area, "朝向" : chaoxiang, "楼层" : louceng
, "建造时间" : time, "每平方米/万元" : one_price, "总房价" : total_price, "地址" : address})
df.to_csv("58同城房价.csv", encoding = "utf-8", index = True, index_label = "序号")
|