网页请求原理: 在浏览器上输入一个网址,计算机是不理解这个信息的,会向运营商服务器发送请求告知输入网址的IP地址,然后根据IP地址向对应的服务器发送请求,服务器就会返回一个HTML文件,浏览器会解析HTML文件,即我们看到的网页
根据层级关系来进行爬虫
在python里面相同的缩进表示一个代码块
登录,上传文件,发表文章等对服务器产生影响的都是POST请求
GET请求不会对服务器产生任何影响,即只是查看
请求头: 把我们的代码伪装成人而不是python
常见的请求头参数:
1.User_Agent: 浏览器的名称.向服务器发送请求时,服务器通过此参数了解是从何种浏览器发出,以便返回正确的信息,必须设定这个参数,不设定这个参数,服务器就知道你是用python等工具来爬取数据,此时,服务器设置了反爬,就会拒绝你的请求
2.Referer :表明网页是从哪个网站跳转过来的.有些网页只能从特定的链接跳转过来,如果不设置,一些网页就能检测到你是通过非浏览器方式试图获取他们的html页面,就不会到那会数据. 通过该参数使用来进行反爬虫设计,我们需要设定这个参数
3.Cookie: HTTP协议是无状态的.我们在浏览器上发送了两次请求,服务器不知道这两个请求是否来自同一个人. 因此这时候就用Cookie来做标识. 一般登录后才能访问的网页,这时候就需要发送Cookie信息.
注: 以上的信息,在爬虫时,复制粘贴就可以了. 相当于我们用python"伪装"成了一个浏览器,一个活生生的人去访问服务器,得到html, 并且在html中获取数据,这就是爬虫真正在做的事情
常见的响应状态码:
200 : 请求成功
301 : 永久重定向,资源(网页等)被永久转移到其他URL, 也可以得到一个正确的页面, 例如 : www.jingdong.com -> www.jd.com
404 : 请求的资源(网页等)不存在
500 : 内部服务器出错
URL: 中文是: 全称统一资源定位符,俗称网址. 每一个信息资源在网址上都有唯一的地址,这就是URL 当我们输入的网址不完整时,浏览器会默默地帮我们补充一些 ,例如: https://
URL的组成 : URL遵守以下的语法规则 : scheme://host:port/path/?query-string=xxx#anchor
scheme- 定义因特网的服务的类型,即访问因特网的协议. 常见的协议有 http, https, file, ftp
1. Http协议: 超文本传输协议,是一种发布和接收HTML页面的协议. 默认服务端口为80端口
2.Https协议: 是HTTP协议的加密版本,在HTTP下加入了SSL层. 默认服务端口为443端口
3.FTP协议: 文件传输协议
4.FILE协议: 本地文件传输协议
http为明文传输,不安全,容易被截取相关信息
host -主机名,域名(比如 www.baidu.com)
port-定义主机上的端口(http默认端口是80, https的默认端口是443)
path-定义服务器的路径(如果省略,则文档必须位于网站的根目录中)
query-string- 定义文档/资源的名称
anchor-网页锚点,前段用来做网页定位
爬虫的流程:
1.得到HTML页面: 即发送http请求
2.按照规则进行数据的提取
3.数据的存储:excel txt csv sql
获取html文件的两种方式:
1. response.text 这种方式可能会有乱码, 因为这种方法是python自己猜测网页的编码方式,大部分中文网站为utf-8
print(response.encoding)可以查看python用了哪种编码解析
print(response.status_code)可以查看返回的状态码
2.response.content.decode("utf8") 按照指定的编码方式解析
在网络中数据是由bytes传输的
所以在用get()获取网络的HTML时,如果在路径中输入中文,有时会传输错误
在用get()方法时,可以借助字典来填写完整的URL
例如: https://www.baidu.com/s
keyword = {
"wd" = "番茄"
}
response = resquest.get(url,pararms = wd)//即利用字典拼接合成的URL
params是个指定路径的关键字
当你用python模仿的不够真时,服务器可能会返回一个假的HTML文件
一次浏览一次Cookie,例如: 登录前的Cookie和登录后的信息, 未设定Cookie信息爬取登录后的QQ空间时得到的HTML文件,打开是为登录页面,而不是已经登录过的页面, 因为登录前后的Cookie是不同的,此时服务器会认为你没有登录进去
请求头参数一般是越完整越好,字典中的元素用逗号隔开
模拟登录:
data = {
"name" = "账号名",
"password" = "密码"
}
session = resquest.session()
session.post(url, data = data, headers = headers)
登陆成功:
response = resquest.get("网址",headers)
content = response.content.decode("utf8')//指定解析编码方式
with open(python.html, 'w',encoding='utf8') as f:
f.write(content)
大部分网站的Form Data都在login里面
很多网站为了设置反爬, 将实际网站隐藏在检查中的代码里面(https请求中 )
为什么要登录: 因为登录前和登录后的内容不一样
爬虫数据提取一般有三种方式 :
1.Xpath
2.bs4
3.正则表达式
Xpath : XML path language 一门在XML 和HTML文档中查找信息的语言, 可用来在XML和HTML文档中对元素和属性进行遍历. 简单来说,我们的数据是超文本数据,要想获取超文本数据里的内容,就要按照一定规则对数据进行获取, 这种规则就叫做Xpath语法.
正因为HTML有强烈的层级关系,Xpath语法能够选择出我们想要的数据
//div 表示全局搜索所有的div标签
//div/head 表示所有的div标签下的head标签
[@]在@后面添加属性, 将含有该标签属性的部分提取出来
后面加上/text()表示爬取文本信息
某个标签下/@属性 会爬取属性的值: 例如 : //div/span/@title 会打印title的值
表示爬取span标签下的文本是"制片国家/地区:"的后面的第一个文本
用request获取到content是还有HTML内容的字符串 不是HTML
不能用Xpath直接对content进行操作
我们使用xtml库对HTML字符串进行解析,,将他还原成一个HTML页面,供Xpath进行数据提取的操作
将HTML字符串转换成HTML文件:
用到lxml的etree的HTML方法:例如
from lxml import etree
html = etree.HTML(text) #text是一个HTML字符串
打印:
eresult = etree.tostring(html, encoding = "utf8").decode("utf8")#encoding="utf8"是告诉其编码的格式,第二个"utf8"是指定解码格式
对于百度网页另存在桌面上然后用etree.parse()解析是错误的
因为百度页面的有些标签是缺失的不够规整,我们默认使用的是xml解析器,当它解析HTML页面时会造成一些错误,所以需要我们自定义解析器
利用parse对HTML文件(不是保存HTML的字符串流)进行解析 格式 :
html = etree.parse(r'文件地址')
result = etree.tostring(html, encoding = "utf8").decode('utf8')
print(result)
解决方法: 传给parse一个自定义解析器
利用parse对HTML文件(不是保存HTML的字符串流)进行解析 格式 :
parser = etree.HTMLparser(ecoding = 'utf8')#自定义个制定解码方式为utf8的解析器
html = etree.parse(r'文件地址', parser = parser)#传给其
result = etree.tostring(html, encoding = "utf8").decode('utf8')
print(result)
python不能直接打印HTML 要用tostring先编码再解码:
例如:
html = etree.HTML(text)#text是保存HTML字符串的
divs = html.xpath("//div")#提取出所有的div标签
for div in divs:
d = etree.tostring(div, encoding = 'utf8').decode("utf8")
print(d)
获取所有div的id='even'的标签:
divs = html.xpath("//div[@id='even']")
获取div标签的id属性的值:
divs = html.xpath("//div/@id")
divs = html.xpath("//div")[1:] #表示从第二个div标签开始取
"."的运用, 例如 :
divs = html.xpath("//div") [1:]
for div in divs:
p = div.xpath(".//a/text()")[0]# 表示获取所有的div标签下的a标签下的文本信息
d = div.xpath(".//a/@href")[0]# 表示 div//a/@href 而不是所有的a标签下的href属性
如果不加[0], d = div.xpath(".//a/@href")的结果是一个列表,加上[0]表示提取一个字符串形式的内容,列表中的第一个内容
print(d)
xpath返回的必定是列表, 列表无法用etree中的函数进行操作
爬虫步骤:
1.导入必要的库或模块
2.定义网页和请求头
3.获取html页面(注意编码和转码的问题)
4.etree解析
5.观察网页源码,查看便签特征
6.编写xpath语法,获取标签内容(文本信息末尾添加/text())
7.存储数据(zip函数双循环)