目录
一、关于爬虫
1.1 概念
网络爬虫,又被称为网页蜘蛛,网络机器人,就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序。原则上,只要是浏览器(客户端)能做的事情,爬虫都能够做。简单来说:爬虫是用事先写好的程序去抓取网络上的数据,这样的程序叫爬虫。
1.2 爬虫的分类
按照使用场景来分,可以分为两类:通用爬虫 和 聚焦爬虫
1.通用爬虫:搜索引擎爬虫,抓取系统重要组成部分。抓取的是一整张页面数据。列如:百度搜索引擎。
2.聚焦爬虫:获取想要的数据,是建立在通用爬虫的基础之上。抓取的是页面中特定的局部内容。
3.增量式爬虫:检测网站中数据更新的情况。只会抓取网站中最新更新出来的数据。
1.3 爬虫的流程原理
1.首先选取一部分精心挑选的种子URL;
2.将这些URL放入待抓取URL队列;
3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
4.分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。
1.4 HTTP协议
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
1.HTTP基于TCP/IP协议:http协议是基于TCP/IP协议之上的应用层协议。
2.HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
3.HTTP是基于请求-响应模式:HTTP协议规定,请求从客户端发出,最后服务器端响应该请求并 返回。
4.HTTP是无状态保存:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
1.5 HTTP之URL
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息。
HTTP URL (URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息)的格式如下:
http://host[":"port][abs_path]
即:http://IP地址:端口号/请求资源的URI
HTTP表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址;port指定一个端口号,为空则使用缺省端口80;abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。url是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。对外的资源一定有URL,但URL不一定有相应的资源。服务器端资源需要通过浏览器进行,此时由浏览器将我们给出的请求解析为满足HTTP协议的格式并发出。我们发出的请求格式需要按照浏览器规定的格式来书写(就是一个URL),在浏览器中书写格式如下:
例子解析:http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
协议部分:该URL的协议部分为“http:”;
域名部分:该URL的域名部分为“www.aspxfans.com”;
端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符;
虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”
文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名。
锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分。
参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
1.6 HTTP之Request
结构:
常见的请求头(报文体):
accept:浏览器通过这个头告诉服务器,他支持的数据类;
Accept-Charset:浏览器通过这个告诉服务器,他锁支持的字符集;
Accept-Encoding:浏览器通过这个告诉服务器,他支持的压缩格式;
Accept-Language:浏览器通过这个告诉服务器,他的预言环境;
Host:浏览器通过这个告诉服务器,像访问那台主机;
If-Modified-Since:浏览器通过这个头告诉服务器,缓存数据的时间;
Referer:浏览器通过这个头告诉服务器,客户机是从哪个页面来的(防盗链);
Connection:浏览器通过这个头告诉服务器,请求完后是断开连接还是维持连接;
X-Requested-With:XMLHttpResquest 代表通过ajax方式进行访问的;
User-Agent:请求载体的身份标识。
1.7 HTTP之Response
结构 :
常见的响应头信息:
- Location:服务器通过这个头,来告诉浏览器跳转到哪里;
- Server:服务器通过这个头,告诉路浏览器服务器的型号;
- Content-Encoding:服务器通过这个头,告诉浏览器数据压缩的格式;
- Content-Length:服务器通过这个头,告诉浏览器会送数据的长度;
- Content-Language:服务器通过这个头,告诉浏览器语言环境;
- Content-Type:服务器通过这个头,告诉浏览器回送数据的类型;
- Refresh:服务器通过这个头,告诉浏览器定时刷新;
- Content-Disposition:服务器通过这个头,告诉浏览器以下载方式打开数据;
- Transfer-Encoding:服务器通过这个头,告诉浏览器数据是以块方式回送的;
- Expires:-1 控制浏览器不要缓存;
- Cache-Control:no-cache
- Pragma: no-cache
二、Requests模块
requests模块:python中原生的一款基于网络请求的模块,功能非常强大,简单便捷,效率极高。
作用:模拟浏览器发请求。
requests模块的编码流程:
- 指定url
- UA伪装
- 请求参数的处理
- 发起请求
- 获取响应数据
- 持久化存储
1.1 基本用法
response = requests.get(url)
response.status_code #状态码
response.url #请求的url
response.headers #头消息
response.cookies #cookies信息
response.text #网页源码
response.content #以字节流方式查看网页源码
1.2 请求方式
requests.get
如:r = requests.get(url='https://api.github.com/events')
requests.post
如:r = requests.post(url='http://httpbin.org/post', data={'key':'value'})
requests.put
如:r = requests.put(url='http://httpbin.org/put', data={'key':'value'})
requests.delete
如:r = requests.delete(url='http://httpbin.org/delete’)
requests.head
如:r = requests.head(url='http://httpbin.org/get')
requests.options
如:r = requests.optinos(url='http://httpbin.org/get')
1、Get请求:
1、将参数直接放在url内:
response = requests.get(url?name='zhangsan')
2、先将参数填在dict内,发起请求时params参数指定为dict
data = {'name':'zhangsan'}
response = requests.get(url,params = data)
2、Post请求 :
data = {'name':'zhangsan'}
response = requests.post(url,data = data)
3、解析Json简单保存二进制文件:
response.json() 方法同json.loads(response.text)
type(response.json())
<class 'dict'>
4、简单保存二进制文件:
二进制内容为response.content
with open(file,'wb') as f:
f.write(response.content)
5、填写头信息:
heads = {}
heads['User-Agent'] = 'xxxxxxxxxxx'
xxxxxxxxxx = xxxxxxxxxx
requests.get(URL,headers = heads)
三、数据解析
3.1 概念:
正则表达式是一个特殊的字符序列,它能帮助我们方便的检查一个字符串是否与某种模式匹配。re 模块使 Python 语言拥有全部的正则表达式功能。compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
3.2 数据解析分类:
- 正则
- bs4
- xpath
3.3 数据解析原理概述:
- 解析的局部的文本内容都会在标签之间或者标签对应的属性中进行存储
- 1.进行指定标签的定位
- 2.标签或者标签对应的属性中存储的数据值进行提取(解析)
3.4 正则解析:
1、常用正则表达式
单字符:
数量修饰:
边界:
正则表达式修饰符:
2、实例:
<div class="thumb">
<a href="/article/121721100" target="_blank">
<img src="//pic.qiushibaike.com/system/pictures/12172/121721100/medium/DNXDX9TZ8SDU6OK2.jpg" alt="指引我有前进的方向">
</a>
</div>
ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
3.5 bs4数据解析
因为BeautifulSoup对象是存在bs4库中的。而lxml是一个解析器,bs4将网页字符串生成对象的时候需要用到解析器,就用lxml,或者使用官方自带的解析器 html.parser。我们用bs4和xpath进行数据解析时都需要这个解析器。
bs4它的作用是能够快速方便简单的提取网页中指定的内容,给我们一个网页字符串,然后使用它的接口将网页字符串生成一个对象,然后通过这个对象的方法来提取数据。
1、基本语法
获取本地 html 页面
# 读取文件
fp = open("./data/base/taobao.html", "r", encoding="UTF-8")
# 数据加载到该对象中 (本地的 html 文件)
html = BeautifulSoup(fp, "lxml")
print(html)
读取网站获取 html 页面
# 爬取页面
response_text = requests.get(url="https://s.taobao.com/").text
# 数据加载到该对象中 (网络的 html 文件)
html = BeautifulSoup(response_text, "lxml")
print(html)
2、获取标签
soup.<tagName>
默认第一个, 没有该标签返回 None
获取当网页下第一个标签“a”,“img”,“input”的所有内容:
print(html.a)
print(html.img)
print(html.input)
soup.find(<tagName>)
等同于 soup.<tagName> 默认第一个
意义同上,获取当网页下第一个标签“a”,“img”,“input”的所有内容:
print(html.find("a"))
print(html.find("img"))
print(html.find("input"))
soup.find(<tagName>, <tagName.class>)
标签属性定位, 包含 <tagName.class> 便可以搜索出来
获取当前页面上的标签中含有<tagName.class>的所有内容;
print(html.find("div", class_="site-nav"))
soup.find_all(<tagName>)
所有标签, 返回值为 List
soup.select(<select>)
运用类选择器查找标签, 所有标签, 返回值为 List
查找当前页面中所有名为“a”,“input”....的标签及其中内容:
print(html.find_all("a"))
print(html.find_all("input"))
print(html.select(".bang"))
print(html.select("#J_SearchForm .search-button"))
print(html.select(".copyright"))
3、获取标签中的内容
text/get_text()
: 获取所有的内容string
获取直系的内容
获取该标签下的文本内容和其直系内容:
print(html.find("div", class_="search-button").text)
print(html.find("div", class_="search-button").string)
print(html.find("div", class_="search-button").get_text())
4、 获取标签属性
[<attribute>]
print(html.a["href"])
print(html.find("div")["class"])
print(html.find_all("div")[5]["class"])
3.6 XPath解析
最常用且最便捷高效的一种解析方式。通用性。
xpath解析原理:
- 1.实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
- 2.调用etree对象中的xpath方法结合着xpath表达式实现标签的定位和内容的
1、实例化ethree
from lxml import etree
①将本地的html文档中的源码数据加载到etree对象中
etree.parse(filepath)
//filepath是html文档的路径
②可以将互联网上获取的源码数据加载到该对象中
etree.HTML('page_text')
//page_text是获取的响应数据
2、Xpath表达式
①定位
Ⅰ.根据层级进行多个标签定位
从根节点开始进行定位/html/body/div
/表示一个层级
例如:/html/body/div
//表示多个层级
例如:/html//div
//可以表示从任意位置开始定位
例如://div
./表示从当前目录开始
例如:div.xpath('./ul')表示之前取到的div下的ul
以上三个表达式表示结果相同
Ⅱ.根据属性进行准确标签定位
tree.xpath('//div[@class="属性名称"]')
Ⅲ.根据id进行准确定位
tree.xpath('//div[@id="标签ID值"]')
Ⅳ.根据索引号进行定位
注意:索引号从1开始,而不是0
tree.xpath('//div[@class="属性名称"]/p[3]')
//该属性class下的第③个p标签
②取值
Ⅰ.获取文本
直系文本:/text()
所有文本://text()
Ⅱ.获取属性/@属性名称
获取img下面的src属性img/@src