目录
1. 网络与网页基础
1.1 网络
1.1.1 http协议
HTTP是客户端(用户)和服务器端(网站)之间进行请求和应答的标准。
- 客户端发送请求:
通过使用网页浏览器、网络爬虫或者其他工具,客户代理(user agent)可以向服务器上的指定端口(默认端口为80)发起一个HTTP请求。 - 服务器端接收请求:
应答服务器上存储着一些资源如HTML文件和图像。
在用户代理和源服务器中间可能存在多个“中间层”,比如代理服务器、网关或者隧道(tunnel)。尽管TCP/IP是互联网最流行的协议,但HTTP中并没有规定必须使用它或它支持的层。事实上,HTTP可以在互联网协议或其他网络上实现。HTTP假定其下层协议能够提供可靠的传输,因此,任何能够提供这种保证的协议都可以使用。
使用TCP/IP协议族时RCP作为传输层。通常由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP链接。HTTP服务器则在该端口监听客户端的请求。一旦收到请求,服务器会向客户端返回一个状态(比如“THTTP/1.1 200 OK”),以及请求的文件、错误信息等响应内容。
1.1.2 HTTP请求
-
get:从指定的资源请求数据
查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:
/test/demo_form.asp?name1=value1&name2=value2
使用get方法时应注意:- GET 请求可被缓存
- GET 请求保留在浏览器历史记录中
- GET 请求可被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET 请求有长度限制
- GET 请求只应当用于取回数据
-
post:向指定的资源提交要被处理的数据
向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求文本中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的。
使用POST 请求时注意:- POST 请求不会被缓存
- POST 请求不会保留在浏览器历史记录中
- POST 不能被收藏为书签
- POST 请求对数据长度没有要求
-
HEAD 请求资源
与GET类似向指定的资源发出“显示”请求,它的好处在于服务器将不会出传回资源的内容部分,可以在不必传输内容的情况下,将获取到其中“关于该资源的信息”(元信息或元数据)。 -
PUT:向指定资源位置上传输最新内容
-
DELETE:请求服务器删除Request-URL所标识的资源,或二者皆有
-
TRACE:回显服务器收到的请求,主要用于测试或诊断
-
OPTIONS:这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用“*”来代表资源名称向Web服务器发送OPTIONS请求,可以测试服务器共能是否正常。
-
CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
通常用于SSL加密服务器的连接(经由非加密的HTTP代理服务器)。方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed),当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。
1.2 HTML 页面
1.2.1 CSS
层叠样式表(Cascading Style Sheets)是一种用来表现HTML或XML等文件样式的计算机语言。
CSS 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象和 模型样式编辑的能力。
CSS 规则由两个主要的部分构成: 选择器, 以及一条或多条声明。
selector {declaration1; declaration2; ... declarationN }
1.2.2 HTML DOM
根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点:
-
整个文档是一个文档节点
-
每个 HTML 元素是元素节点
-
HTML 元素内的文本是文本节点
-
每个 HTML 属性是属性节点
-
注释是注释节点
HTML DOM 将 HTML 文档视作树结构。这种结构被称为节点树:
通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点。
节点树中的节点彼此拥有层级关系。
父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点。同级的子节点被称为同胞(兄弟或姐妹)。
-
在节点树中,顶端节点被称为根(root)
-
每个节点都有父节点、除了根(它没有父节点)
-
一个节点可拥有任意数量的子
-
同胞是拥有相同父节点的节点
下面的图片展示了节点树的一部分,以及节点之间的关系:
1.2.3 开发者工具
工具 | 说明 |
---|---|
Elements | 从浏览器的角度看到Chrome渲染页面所需要的HTML、CSS和DOM(Document Object Model)对象。 |
Network | 可以看到网页向服务气请求了哪些资源、资源的大小以及加载资源的相关信息。此外,还可以查看HTTP的请求头、返回内容等。 |
Source | 源代码面板,主要用来调试JavaScript。 |
Console | 控制台面板,可以显示各种警告与错误信息。在开发期间,可以使用控制台面板记录诊断信息,或者使用它作为shell在页面上与JavaScript交互。 |
Performance | 使用这个模块可以记录和查看网站生命周期内发生的各种事情来提高页面运行时的性能。 |
Memory | 提供比Performance更多的信息,比如跟踪内存泄漏。 |
Application | 检查加载的所有资源 |
Security | 安全面板,可以用来处理证书问题等 |
-
切换设备显示效果
通过切换设备模式可以观察网页在不同设备上的显示效果,快捷键为:Ctrl + Shift + M(或者在 Mac上使用 Cmd + Shift + M),如下图所示。
-
Element编辑元素
在“Element”面板中,开发者可以检查和编辑页面的HTML与CSS。选中并双击元素就可以编辑元素了,比如将“python”这几个字去掉,右键该元素,选择“Delete Element”,效果如下图所示:
由于XPath是解析网页的利器,因此Chrome中的快捷菜单中的“Copy XPath”选项对于爬虫程序编写而言十分实用和方便。 -
Network查看网页加载网络资源过程和相关信息
每个请求的资源在“Network”表格中显示为一行。
对于某个特定的网络请求,可以进一步查看请求头、响应头及已经返回的内容等信息。 -
Preserve log 记录post信息
对于需要填写并发送表单的网页(比如执行用户登录操作),在“Network”面板勾选“Preserve log”复选框,然后进行登录,就可以记录HTTP POST信息,查看发送的表单信息详情。
- “Preview”:也比较常用,可以用来预览数据。
2. requests库的基本应用
一个网络爬虫程序最普遍的过程:
- 访问站点;
- 定位所需的信息;
- 得到并处理信息。
2.1 get方法
#使用get方法进行请求输出的结果
import requests
url='http://www.baidu.com'
responses=requests.get(url)
print('requests.get方法返回值:',responses)
print('type(responses):',type(responses))
print()
print('responses.status_code:',responses.status_code)
print('responses.encoding:',responses.encoding)
#修改网页编辑为utf-8
responses.encoding = 'utf-8'
print('responses.encoding(修改编码后):',responses.encoding)
print()
# responses.text返回的是开发者工具下Elements的内容,字符串类型
print('请求后得到的网页html源码:',responses.text)
利用python自带的urllib库完成以上操作
使用urllib.request.urlopen获得的response
# 使用urllib.request.urlopen获得的response
import urllib
url='http://www.baidu.com'
# # 利用urlopen方法向目标网址发送请求,并将请求结果存入response
respones=urllib.request.urlopen(url=url)
print(respones)
print('----------------')
print(respones.read())
2.2 post方法
使用request.post 获得response:
headers={"User-Agent" : "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
"Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language" : "en-us",
"Connection" : "keep-alive",
"Accept-Charset" : "GB2312,utf-8;q=0.7,*;q=0.7"}
r=requests.post("http://baike.baidu.com/item/火影忍者",headers=headers,allow_redirects=False) #allow_redirects设置为重定向
r.encoding="UTF-8"
print(r.url)
print(r.text)
print(r.headers) #响应头
print(r.request.headers) #请求头
3. 爬取豆瓣250
import requests
import os
if not os.path.exists('image'):
os.mkdir('image')
def parse_html(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"} # 伪装头部信息
res = requests.get(url, headers=headers)
text = res.text
item = []
for i in range(25):
text = text[text.find('alt')+3:]
item.append(extract(text))
return item
def extract(text):
text = text.split('"')
name = text[1]
image = text[3]
return name, image
def write_movies_file(item, stars):
print(item)
with open('C:/userdouban_film.txt','a',encoding='utf-8') as f:
f.write('排名:%d\t电影名:%s\n' % (stars, item[0]))
r = requests.get(item[1])
with open('image/' + str(item[0]) + '.jpg', 'wb') as f:
f.write(r.content)
def main():
stars = 1
for offset in range(0, 250, 25):
url = 'https://movie.douban.com/top250?start=' + str(offset) +'&filter='
for item in parse_html(url):
write_movies_file(item, stars)
stars += 1