Request模块—数据解析工具

一、爬虫基本步骤

  • 指定URL信息
  • 发起请求
  • 获取响应数据
  • 对响应数据进行数据解析
  • 持久化存储

二、数据解析

1. 正则表达式

(1) 基本语法
1. 单字符:
	. : 除换行以外所有字符
	[] :[aoe] [a-w] 匹配集合中任意一个字符
	d :数字  [0-9]
	D : 非数字
	w :数字、字母、下划线、中文
	W : 非w
	s :所有的空白字符包,括空格、制表符、换页符等等。等价于 [ f

	v]。
	S : 非空白
2. 数量修饰:
	* : 任意多次  >=0
	+ : 至少1次   >=1
	? : 可有可无  0次或者1次
	{m} :固定m次 hello{3,}
	{m,} :至少m次
	{m,n} :m-n次
3. 边界:
	$ : 以某某结尾
	^ : 以某某开头
4. 分组:
	(ab)  
5. 贪婪模式: .*
6. 非贪婪(惰性)模式: .*?
7. 爬虫正则
	re.I : 忽略大小写
    re.M :多行匹配
    re.S :单行匹配  //爬虫常用
    re.sub(正则表达式, 替换内容, 字符串)
(2) 相关案例
import re
# 提取出python
key="javapythonc++php"
re.findall('python',key)[0]
-----------------------------------------------------------------------------------------
# 提取出hello world
key="<html><h1>hello world<h1></html>"
re.findall('<h1>(.*)<h1>',key)[0]
-----------------------------------------------------------------------------------------
# 提取170
string = '我喜欢身高为170的女孩'
re.findall('d+',string)
-----------------------------------------------------------------------------------------
# 提取出http://和https://
key='http://www.baidu.com and https://boob.com'
re.findall('https?://',key)
-----------------------------------------------------------------------------------------
# 提取出hello
key='lalala<hTml>hello</HtMl>hahah' #输出<hTml>hello</HtMl>
re.findall('<[Hh][Tt][mM][lL]>(.*)</[Hh][Tt][mM][lL]>',key)
-----------------------------------------------------------------------------------------# 提取出hit.
key='bobo@hit.edu.com'  # 想要匹配到hit.
re.findall('h.*?.',key)
-----------------------------------------------------------------------------------------
# 匹配sas和saas
key='saas and sas and saaas'
re.findall('sa{1,2}s',key)
-----------------------------------------------------------------------------------------
# 匹配出i开头的行
string = '''fall in love with you
i love you very much
i love she
i love her'''

re.findall('^.*',string,re.M)
-----------------------------------------------------------------------------------------
# 匹配全部行
string1 = """<div>静夜思
窗前明月光
疑是地上霜
举头望明月
低头思故乡
</div>"""

re.findall('.*',string1,re.S)

2. Beautifulsoup

(1) 环境安装
- 需要将pip源设置为国内源,阿里源、豆瓣源、网易源等
   - windows
    (1)打开文件资源管理器(文件夹地址栏中)
    (2)地址栏上面输入 %appdata%
    (3)在这里面新建一个文件夹  pip
    (4)在pip文件夹里面新建一个文件叫做  pip.ini ,内容写如下即可
        [global]
        timeout = 6000
        index-url = https://mirrors.aliyun.com/pypi/simple/
        trusted-host = mirrors.aliyun.com
   - linux
    (1)cd ~
    (2)mkdir ~/.pip
    (3)vi ~/.pip/pip.conf
    (4)编辑内容,和windows一模一样
- 需要安装:pip install bs4
     bs4在使用时候需要一个第三方库,把这个库也安装一下
     pip install lxml
(2) 基础使用
1. 使用流程:       
    - 导包:from bs4 import BeautifulSoup
    - 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点
    
2. 内容
	(1)转化本地文件:
		- soup = BeautifulSoup(open('本地文件'), 'lxml')
	(2)转化网络文件:
		- soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')
	(3)打印soup对象显示内容为html文件中的内容
    
3. 基础巩固:
    (1)根据标签名查找
        - soup.a   只能找到第一个符合要求的标签
    (2)获取属性
        - soup.a.attrs  获取a所有的属性和属性值,返回一个字典
        - soup.a.attrs['href']   获取href属性
        - soup.a['href']   也可简写为这种形式
    (3)获取内容
        - soup.a.string
        - soup.a.text
        - soup.a.get_text()
       【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个可以获取文本内容
    (4)find:找到第一个符合要求的标签
        - soup.find('a')  找到第一个符合要求的
        - soup.find('a', title="xxx")
        - soup.find('a', alt="xxx")
        - soup.find('a', class_="xxx")
        - soup.find('a', id="xxx")
    (5)find_all:找到所有符合要求的标签
        - soup.find_all('a')
        - soup.find_all(['a','b']) 找到所有的a和b标签
        - soup.find_all('a', limit=2)  限制前两个
    (6)根据选择器选择指定的内容
               select:soup.select('#feng')
        - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
            - 层级选择器:
                div .dudu #lala .meme .xixi  下面好多级
                div > p > a > .lala          只能是下面一级
        【注意】select选择器返回永远是列表,需要通过下标提取指定的对象

3. xpath

(1) 选取节点
表达式 描述
nodename 选取此节点的所有子节点
/ 从根节点选取
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
(2) 案例
路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点
/bookstore 选取根元素 bookstore;注释:假如路径起始于正斜杠( / )则此路径始终代表到某元素的绝对路径
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素
//book 选取所有 book 子元素,而不管它们在文档中的位置
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置
//@lang 选取名为 lang 的所有属性
(3) 谓语
表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素
/bookstore/book[position()❤️] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00
(4) 选取位置节点
表达式 结果
* 匹配任何元素节点
@* 匹配任何元素属性节点
node() 匹配任何类型的节点
路径表达式 结果
/bookstore/* 选取bookstore元素的所有子元素
//* 选取文档中的所有元素
//title[@*] 选取所有带属性的title元素
路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素
//title | //price 选取文档中的所有 title 和 price 元素
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素
(5) 基本案例
1. 属性定位:
    #找到class属性值为song的div标签
    //div[@class="song"]
2. 层级&索引定位:
    #找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
    //div[@class="tang"]/ul/li[2]/a
3. 逻辑运算:
    #找到href属性值为空且class属性值为du的a标签
    //a[@href="" and @class="du"]
4. 模糊匹配:
    //div[contains(@class, "ng")]
    //div[starts-with(@class, "ta")]
5. 取文本:
    # /表示获取某个标签下的文本内容
    # //表示获取某个标签下的文本内容和所有子标签下的文本内容
    //div[@class="song"]/p[1]/text()
    //div[@class="tang"]//text()
6. 取属性:
    //div[@class="tang"]//li[2]/a/@href

三、流程

1.下载:pip install lxml

2.导包:from lxml import etree

3.将html文档或者xml文档转换成一个etree对象,然后调用对象中的方法查找指定的节点
	2.1 本地文件: tree = etree.parse(文件名)
                 tree.xpath("xpath表达式")
    2.2 网络数据:tree = etree.HTML(网页内容字符串)
                 tree.xpath("xpath表达式")
        
4.备注:
    安装Chrome的xpath插件
    安装xpath插件在浏览器中对xpath表达式进行验证:可以在插件中直接执行xpath表达式
	将xpath插件拖动到谷歌浏览器拓展程序(更多工具)中,安装成功
    启动和关闭插件 ctrl + shift + x
  	
5.xpath解析原理
- 实例化一个etree的对象,且将页面源码数据加载到该对象中    
- 调用etree对象中的xpath方法实现标签定位和数据的提取    
- 在xpath函数中必须作用xpath表达式    
- xpath函数返回的一定是一个列表
原文地址:https://www.cnblogs.com/hq82/p/10792698.html