结构化数据
类似于动态加载的 先有结构后有数据
json
非结构化数据
现有数据 后有结构
正则
个人感觉,正则是匹配数据最快的,但也是最难的。
之前写过正则的匹配,这里就不多说了。
Xpath
表达式 | 描述 |
---|---|
/ | 从根节点开始 |
// | 从匹配选择的当前节点选择文档中的节点,不考节点虑位置 |
. | 选取当前节点 |
… | 选取当前节点的父节点 |
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position() < 3] | 选取属于 bookstore 元素的子元素的最前面的两个 book 元素。 |
//title[@lang=“xxxx”] | 选取所有拥有名为 lang 的属性为xxxx的 title 元素。 |
@ | 选取属性 |
text() | 选取文本内容 |
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
栗子说:“来人,上干货!!”
from lxml import etree
import requests
response = requests.get('https://bj.lianjia.com/zufang')
html = etree.HTML(response.text)
ul_list = html.xpath('//ul[@id="house-lst"]/li')
for li in ul_list:
dic = {}
# 图片链接
dic['img_url'] = li.xpath('./div[@class="pic-panel"]//img/@src')[0]
# 标题
dic['title'] = li.xpath('.//div[@class="info-panel"]/h2/a/text()')[0]
# 四个地址
dic['address'] = '| '.join(li.xpath('.//div[@class="info-panel"]//div[@class="where"]//span/text()'))
# 房屋详情
dic['other'] = ' |'.join(li.xpath('.//div[@class="info-panel"]//div[@class="con"]/text()') + \
li.xpath('.//div[@class="info-panel"]//div[@class="con"]/a/text()'))
# 价格
dic['price'] = li.xpath('.//div[@class="price"]/span/text()')[0]
# 更新
dic['up_date'] = li.xpath('.//div[@class="price-pre"]/text()')[0]
# 看过
dic['look'] = li.xpath('.//div[@class="square"]//span/text()')[0] + '看过'
print(dic)
BeautifulSoup / CSS 选择器
- prettify() 可以将html代码格式化输出
- find()----查找第一个节点
- 参数:
name :可以是字符串,列表,正则表达式 (标签的名称)
attrs:收一个字典(标签的属性)
text:字符串,列表(查找出所有根text文本一样的内容)
- 参数:
- find_all():查找所有的节点 用法和find一样
bs4.BeautifulSoup以及bs4.element.Tag对象能够使用find_all方法
html_soup.find_all('li'):查找所有li标签 html_soup.find_all(['li','a']):查找所有li标签和a标签 html_soup.find_all(re.compile('^b')): 查找所有符合正则表达式的标签 html_soup.find_all(name='ul',attrs={'class':'article'}) html_soup.find_all(name='ul', attrs={'id': 'Ul1'})
- . 点表示类选择器
html_soup = BeautifulSoup(response.text,'html.parser') publish_time = html_soup.select('span.fn-left')
- # 表示id选择器
html_soup = BeautifulSoup(response.text,'html.parser') id_li = html_soup.select('li#ad_tw_04')[0]
栗子又说:“在来一次啊~~~~~~”
from lxml import etree
import requests
response = requests.get('https://bj.lianjia.com/zufang')
#首先创建一个soup对象
#'lxml':说明使用的是lxml.html解析器(速度快,容错性也比较高)
#'html.parser':python模块自带的html解析器
html = BeautifulSoup(response.text,'html.parser')
ul_list = html.select('ul#house-lst li')
for li in ul_list:
dic = {}
# 图片链接
dic['img_url'] = li.select('div.pic-panel img')[0].attrs['src']
# print(dic['img_url'])
# 标题
dic['title'] = li.select('div.info-panel h2 a')[0].get_text()
print(dic['title'])
pyQuery
- 构建pyQuery对象的方式:
- pq_html = pq(response.text) —> 直接传入网页源码
- pq_html1 = pq(etree.fromstring(response.text)) ----> 传入lxml解析以后的html
- pq_html2 = pq(‘https://ww.baidu.com’) —>传入url pyQuery会自己请求,拿到请求结果,
不推荐使用,对于复杂的url pyQuery 并不能很友好 - pq_html4 = pq(filename=‘filename’) —> 直接传入文件 并解析
- 提取数据
- 直接使用CSS语法 提取
pq_html = pq(response.text) print(type(pq_html)) tr = pq_html('tr.even') print(type(tr))
- 注意: 这时候 tr 任然是 pyQuery对象
- 注意: 如果想遍历 itemss() 转成生成器(generator)
tr_list = tr.items('td') # 这里表示遍历tr 子节点的td标签 # 如果不加参数 则表明不按理tr标签 print(type(tr_list)) for i in tr_list: print(i) print(type(i))
- 进一步提取
- .html() 表示获取某一块代码块
- .text() 表示获取文本内容
- .attr() 获取标签属性值
- .(select(#/.)) 使用bs4 提取
- .eq(index索引) 获取某一个标签
- .find() 找到当前标签下的子节点
- .filter() 过滤获取节点
- .addClass(value):添加 class
- .hasClass(value):—> 判断是否包含指定的 class,返回 True 或 False
- .children(): —> 获取子元素
- .parents(): —> 获取父元素
- .next():—> 获取下一个元素
- .nextAll(): —> 获取后面全部元素块
- .not_(selector):–> 获取所有不匹配该选择器的元素
- 直接使用CSS语法 提取
栗子:
if response.status_code == 200:
print('请求成功')
#构建一个pq对象
html_pq = pq(response.text)
#根据类名赵对应的标签
# tr_even = html_pq('tr').filter('.even')
tr_even = html_pq('tr.even')
#
# tr_odd = html_pq('tr').filter('.odd')
tr_odd = html_pq('tr.odd')
jobs = tr_even + tr_odd
print(type(jobs))
#PyQuer对像不是一个可迭代对象,
# print(type(jobs.items()))
for tr in jobs.items():
# print(tr)
#提取想要的数据
#.text()获取标签的文本
title = tr('td.l.square a').text()
print(title)
#.attr('href')获取标签的属性
url = tr('td.l.square a').attr('href')
print(url)
#获取类型
#.eq(1) 根据索引取标签,所以从0开始
tags = tr('td').eq(1).text()
print(tags)