Requests、BeautifulSoup、re、lxml、css selector 、scrapy
1.Requests
1.1 Requests的7个主要方法
其中,request()方法是其它方法的基础方法,get()方法用的多一些,本人没在实际爬取中用过其它方法。
requests.request() 构造一个请求,支撑以下各方法的基础方法
requests.get() 获取HTML网页的主要方法,对应于HTTP的GET
requests.head() 获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post() 向HTML网页提交POST请求的方法,对应于HTTP的POST
requests.put() 向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.patch() 向HTML网页提交局部修改请求,对应于HTTP的PATCH
1.2 get()方法
r= requests.get(url)
r:返回一个包含服务器资源的Response对象
requests.get(url):构造一个向服务器请求资源的Request对象
requests.get(url, params=None, **kwargs)
1.3 Requests库的2个重要对象(Request、Response)
![这里写图片描述](https://img-blog.csdn.net/20170911155328722?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWxfMTAxOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
由上图所示,request请求返回的是Response对象,可以提取对应的头部等信息。一般而言,除非是需要登录验证的post请求中,需要通过get请求拿到请求的头部信息,然后加到post请求头部信息里,用来登陆验证。
返回的Response对象有以上的属性,其中r.status_code状态码可以进行请求控制。
可以通过检测的编码替换现有的编码,以正常解码。需要注意的是,r.encoding()的执行,耗费的时间相对较多,如果注重效率,编码又比较固定,就考虑用固定编码给r.apparent_encoding赋值,以减少运行时间。
1.4 Response异常
r.raise_for_status() 如果不是200,产生异常 requests.HTTPError
该方法可以用来作请求异常控制的中检测。
1.5 通用框架
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()#检测异常
r.encoding = r.apparent_encoding#改http中给定编码方式为根据文本(r.text)猜测的编码方式。
return r.text
except:
print("请求出错")
return ""
1.6 Requests方法解析(requests.get())
requests.get(url, params=None, **kwargs)
**kwargs
data json
headers cookies
auth files
timeout proxies
allow_redirects stream
verify cert
2.BeautifulSoup
2.1 什么是BeautifulSoup
BeautifulSoup是解析、遍历、维护标签树(html)的库。
**解析html**:解析方式可以有4种,包括lxml。
**遍历标签树**:通过上行下行和平行遍历迭代器遍历,结合基本元素(tag、name、tag.string等等)提取内容。
**维护标签树**:以美观的形式输出html(prettify())
**编码**:bs4库将任何HTML输入都变成utf‐8编码,python3默认支持utf-8
2.2 Beautiful Soup库解析器
如下图所示,一共可以有4中方式,其中解析速度:lxml > html.parser
测试了下,lxml和 html.parser都会将缺失的标签补上。因为lxm是用c写的,所以理论上lxml速度会快些。另外的解析方式不太了解,也没用过,暂不理b( ̄▽ ̄)d
2.3 BeautifulSoup类的基本元素
可以通过基本元素定位和提取标签的内容。如通过[tag].attrs可以以字典的形式提取出标签内属性名字和值。通过[tag].string的方式提取非属性字符串。区别注释的方法是,通过type判断类型。
<p class=“title”>… </p>
基本元素 说明
Tag 标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾
Name 标签的名字,<p>…</p>的名字是'p',格式:<tag>.name
Attributes 标签的属性,字典形式组织,格式:<tag>.attrs
NavigableString 标签内非属性字符串,<>…</>中字符串,格式:<tag>.string
Comment 标签内字符串的注释部分,一种特殊的Comment类型
2.4 基于bs4库的HTML内容遍历方法
BeautifulSoup提供了三种遍历方式,上行、下行和平行 遍历,如下图所示:
(1)下行遍历:
属性 说明
.contents 子节点的列表,将<tag>所有儿子节点存入列表
.children 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历
for child in soup.body.children:
print(child) #遍历儿子节点
for child in soup.body.descendants:
print(child) #遍历子孙节点
(2)上行遍历:
尤其注意画红线部分,所有的先辈节点中包含soup本身。即整个html文档。
(3)平行遍历:
属性 说明
.next_sibling #返回按照HTML文本顺序的下一个平行节点标签
.previous_sibling #返回按照HTML文本顺序的上一个平行节点标签
.next_siblings #迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_siblings #迭代类型,返回按照HTML文本顺序的前续所有平行节点标签
2. 5基于bs4库的HTML格式输出
2.6 BeautifulSoup和lxml的异同
异 同
BS有4种解析方法 都可以用来解析html和xml
BS的接口比较简洁 都支持cssselector和xpath
BS的遍历方式比较多(上 下 平行遍历)
BS容易上手
lxml是用c写的,速度相对较快
3.Re、Xpath、cssSelecor
3.1正则表达式:
正则表达式:用来简洁表达一组字符串的表达式(包括字符和操作符)。
操作符:
表达式实例:
3.2 re模块
import re
string222='1995我 的天哦,我的妈呀 公元1996 1231年'
# 1.—————————————第1种方式(函数式用法)————————————
#findall
ls=re.findall(r'[1-9]\d{3}','1995 公元1996 1231年')
if ls:
print(ls)
#match 匹配到的第一个
match2=re.match(r'[1-9]\d{3}','1995 公元1996 1231年')
if match2:
print(match2.group(0))
#split 以匹配到的字符串分割
ls2=re.split(r'[1-9]\d{3}',string222,maxsplit=1)
if ls2:
print(ls2)
#sub 替换匹配到的字符串
ls3=re.sub(r'[1-9]\d{3}',repl=' 替换了这里 ',string=string222)
print(ls3)
>>>
['1995', '1996', '1231']
1995
['', '我 的天哦,我的妈呀 公元1996 1231年']
替换了这里 我 的天哦,我的妈呀 公元 替换了这里 替换了这里 年
# 2.—————————————法2(函数式用法)————————————
# 一次编译,多次使用
pat=re.compile(r'[1-9]\d{3}')#编译
rst=pat.search(string222) #搜索
print(rst.group(0)) #结果
print(rst.string) #待匹配的文本
print(rst.re) #使用的正则表达式
print(rst.span()) #返回(起始位置,结束位置)
>>>
1995
1995我 的天哦,我的妈呀 公元1996 1231年
re.compile('[1-9]\\d{3}')
(0, 4)
# 3.—————————————match对象————————————
# search和match方法返回的都是match对象
# ##属性
# .string:待匹配的文本
# .re:匹配时使用的pattern对象(正则表达式)
# .pos(正则表达式搜索文本的开始位置)
# .enpos:正则表达式搜索文本的结束位置
# ##方法:
# group(0)
# .start()
# .end()
# .span() 开始合结束位置
# 4.—————————————贪婪匹配(默认)————————————
match3=re.search(r'PY.*N','PYNABNCNDNFFFFF')
print(match3.group(0))
match4=re.search(r'PY.*?N','PYNABNCNDNFFFFF')
print(match4.group(0))
match5=re.search(r'PY.+?N','PYNABNCNDNFFFFF')
print(match5.group(0))
# 有长度的地方就有懒惰
# * → *? 任意次 → 0次
# + → +? 一次以上 → 1次
# ? → ?? 0/1次 → 0次
# {m,n} → {m,n}? m到n次 → m次
>>>
PYNABNCNDN
PYN
PYNABN
3.3 Xpath
# coding=utf-8
el = tree.xpath('//input[@name="authenticity_token"]')[0] #//表示从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。根节点为/
authenticity_token = el.attrib['value']
r = s.post(SESSION_URL, data=data)
el = tree.xpath('//ul[@id="repo_listing"]')[0] #模式为节点[@+属性='值'] 返回列表
el.xpath('//li[contains(@class, "public")]')
#多次截取
print (el.xpath('//span[@class="repo"]')[0].text)
print (tree.xpath('//ul[@id="repo_listing"]//li[contains(@class, "public")]//\span[@class="repo"]')[0].text)
3.4 css selecors:
可转换为xpath执行
from cssselect import GenericTranslator, SelectorError
try:
expression = GenericTranslator().css_to_xpath('div.content')
except SelectorError:
print('Invalid selector.')
print(expression)
输出:descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' content ')]
from lxml.etree import fromstring
document = fromstring('.....')
document.xpath(expression)#执行转换后的cssselector
html解析和提取参考:
1.Python正则表达式
2.CSS 选择器参考手册
3.XPath 语法
4.BeautifulSoup :一些常用功能的使用和测试
5.BeautifulSoup的使用,代码比较乱
4.Scrapy
4.1 Scrapy简介
Scrapy是一个快速功能强大的网络爬虫框架,框架的意思就是不止一个库,是很多模块的集合,只需要进行一些配置就可以实现很powerf的功能。
Scrapy是一个开源、协作的框架。
4.2 Scrapy VS Requests
相同点:
两者都可以进行页面请求和爬取,Python爬虫的两个重要技术路线
两者可用性都好,文档丰富,入门简单
两者都没有处理js、提交表单、应对验证码等功能(可扩展)
不同点:
4.3 Scrapy框架结构
”5+2结构“:5个模块,2个中间件
如下图所示:需要编写和配置的只有spider、 item、pipelines
4.4 Scrapy常用命令
5.Scrapy实例
参见:南方都市报scrapy爬虫
6.爬虫待发掘
6.1 非框架并行爬虫
多线程(效果不太理想,慢、漏)
6.2 会话管理
session 共享等
6.3 ip池、http请求头部池
6.4 分布式爬虫(上云)
以上内容部分整理自:Python网络爬虫与信息提取