python-01 spider原理

用 Python 可以做什么?可以做日常任务,比如自动备份你的 MP3;可以做网站,很多著名的网站包括 YouTube 就是 Python 写的;可以做网络游戏的后台,很多在线游戏的后台都是 Python 开发的。总之就是能干很多很多事啦。

Python 当然也有不能干的事情,比如写操作系统,这个只能用 C 语言写;写手机应用,只能用 Swift/Objective-C(针对 iPhone)和 Java(针对 Android);写 3D 游戏,最好用 C 或 C++。

如果你是小白用户,满足以下条件:

  • 会使用电脑,但从来没写过程序;
  • 还记得初中数学学的方程式和一点点代数知识;
  • 想从编程小白变成专业的软件架构师;
  • 每天能抽出半个小时学习

一、爬虫是什么?

简单来说互联网是由一个个站点和网络设备组成的大网,我们通过浏览器访问站点,站点把 HTML、JS、CSS 代码返回给浏览器,这些代码经过浏览器解析、渲染,将丰富多彩的网页呈现我们眼前;

如果我们把互联网比作一张大的蜘蛛网,数据便是存放于蜘蛛网的各个节点,而爬虫就是一只小蜘蛛,

沿着网络抓取自己的猎物(数据)爬虫指的是:向网站发起请求,获取资源后分析并提取有用数据的程序;

从技术层面来说就是 通过程序模拟浏览器请求站点的行为,把站点返回的 HTML 代码 /JSON 数据 / 二进制数据(图片、视频) 爬到本地,进而提取自己需要的数据,存放起来使用;

二、爬虫的基本流程:

 

用户获取网络数据的方式:

方式 1:浏览器提交请求 ---> 下载网页代码 ---> 解析成页面

方式 2:模拟浏览器发送请求 (获取网页代码)-> 提取有用的数据 -> 存放于数据库或文件中

爬虫要做的就是方式 2;

 

1、发起请求

使用 http 库向目标站点发起请求,即发送一个 Request

Request 包含:请求头、请求体等 

Request 模块缺陷:不能执行 JS 和 CSS 代码

 

2、获取响应内容

如果服务器能正常响应,则会得到一个 Response

Response 包含:html,json,图片,视频等

 

3、解析内容

解析 html 数据:正则表达式(RE 模块),第三方解析库如 Beautifulsoup,pyquery 等

解析 json 数据:json 模块

解析二进制数据: 以 wb 的方式写入文件

 

4、保存数据

数据库(MySQL,Mongdb、Redis)

文件

三、http 协议 请求与响应

 

Request:用户将自己的信息通过浏览器(socket client)发送给服务器(socket server)

Response:服务器接收请求,分析用户发来的请求信息,然后返回数据(返回的数据中可能包含其他链接,如:图片,js,css 等)

ps:浏览器在接收 Response 后,会解析其内容来显示给用户,而爬虫程序在模拟浏览器发送请求然后接收 Response 后,是要提取其中的有用数据。

 

四、 request

1、请求方式:

常见的请求方式:GET / POST

 

2、请求的 URL

url 全球统一资源定位符,用来定义互联网上一个唯一的资源 例如:一张图片、一个文件、一段视频都可以用 url 唯一确定

 

url 编码

https://www.baidu.com/s?wd= 图片

图片会被编码(看示例代码)

 

网页的加载过程是:

加载一个网页,通常都是先加载 document 文档,

在解析 document 文档的时候,遇到链接,则针对超链接发起下载图片的请求

 

3、请求头

User-agent:请求头中如果没有 user-agent 客户端配置,服务端可能将你当做一个非法用户 host;

cookies:cookie 用来保存登录信息

四、 request

1、请求方式:

常见的请求方式:GET / POST

 

2、请求的 URL

url 全球统一资源定位符,用来定义互联网上一个唯一的资源 例如:一张图片、一个文件、一段视频都可以用 url 唯一确定

 

url 编码

https://www.baidu.com/s?wd= 图片

图片会被编码(看示例代码)

 

网页的加载过程是:

加载一个网页,通常都是先加载 document 文档,

在解析 document 文档的时候,遇到链接,则针对超链接发起下载图片的请求

 

3、请求头

User-agent:请求头中如果没有 user-agent 客户端配置,服务端可能将你当做一个非法用户 host;

cookies:cookie 用来保存登录信息

四、 request

1、请求方式:

常见的请求方式:GET / POST

 

2、请求的 URL

url 全球统一资源定位符,用来定义互联网上一个唯一的资源 例如:一张图片、一个文件、一段视频都可以用 url 唯一确定

 

url 编码

https://www.baidu.com/s?wd= 图片

图片会被编码(看示例代码)

 

网页的加载过程是:

加载一个网页,通常都是先加载 document 文档,

在解析 document 文档的时候,遇到链接,则针对超链接发起下载图片的请求

 

3、请求头

User-agent:请求头中如果没有 user-agent 客户端配置,服务端可能将你当做一个非法用户 host;

cookies:cookie 用来保存登录信息

请求头需要注意的参数:

(1)Referrer:访问源至哪里来(一些大型网站,会通过 Referrer 做防盗链策略;所有爬虫也要注意模拟)

(2)User-Agent: 访问的浏览器(要加上否则会被当成爬虫程序)

(3)cookie:请求头注意携带

 

4、请求体

请求体
    如果是 get 方式,请求体没有内容 (get 请求的请求体放在 url 后面参数中,直接能看到)
    如果是 post 方式,请求体是 format data
ps:
1、登录窗口,文件上传等,信息都会被附加到请求体内
2、登录,输入错误的用户名密码,然后提交,就可以看到post,正确登录后页面通常会跳转,无法捕捉到post<br><br></pre>

五、 响应 Response

1、响应状态码

  200:代表成功

  301:代表跳转

  404:文件不存在

  403:无权限访问

  502:服务器错误

 

2、respone header


响应头需要注意的参数:

(1)Set-Cookie:BDSVRTM=0; path=/:可能有多个,是来告诉浏览器,把 cookie 保存下来

(2)Content-Location:服务端响应头中包含 Location 返回浏览器之后,浏览器就会重新访问另一个页面

 

3、preview 就是网页源代码

JSO 数据

如网页 html,图片

二进制数据等 

 

 

六、总结

1、总结爬虫流程:

 爬取 ---> 解析 ---> 存储

 

2、爬虫所需工具:

 请求库:requests,selenium(可以驱动浏览器解析渲染 CSS 和 JS,但有性能劣势(有用没用的网页都会加载);)
 解析库:正则,beautifulsoup,pyquery
 存储库:文件,MySQL,Mongodb,Redis

涉及知识:多线程多进程

计算密集型任务:使用多进程,因为能 Python 有 GIL,多进程可以利用上 CPU 多核优势;

IO 密集型任务:使用多线程,做 IO 切换节省任务执行时间(并发)

线程池

以上参考 https://www.cnblogs.com/sss4/p/7809821.html

接下来动动手指,操作一下

运行平台:Windows 10
Python 版本:Python3.7
IDE:pycharm

 

1 from urllib import request
2 
3 url = 'http://www.baidu.com'
4 # page = request.Request(url)
5 # page.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36')
6 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
7 page = request.Request(url, headers=headers)
8 page_info = request.urlopen(page).read().decode('utf-8')
9 print(page_info)
View Code

 

  • 对于 python 3 来说,urllib 是一个非常重要的一个模块 ,可以非常方便的模拟浏览器访问互联网, 对于 python 3 爬虫来说, urllib 更是一个必不可少的模块, 它可以帮助我们方便地处理 URL.
  • urllib.request 是 urllib 的一个子模块, 可以打开和处理一些复杂的网址

The urllib.request
module defines functions and classes which help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication, redirections, cookies and more.

  • urllib.request.urlopen()方法实现了打开 url, 并返回一个 http.client.HTTPResponse 对象, 通过 http.client.HTTPResponse 的 read() 方法, 获得 response body, 转码最后通过 print() 打印出来.

urllib.request.urlopen(url, data=None, [timeout, ]***, cafile=None, capath=None, cadefault=False, context=None)
For HTTP and HTTPS URLs, this function returns a http.client.HTTPResponse
object slightly modified.
< 出自: https://docs.python.org/3/library/urllib.request.html >

  • decode('utf-8') 用来将页面转换成 utf-8 的编码格式,否则会出现乱码


当然这个前提是我们已经知道了这个网页是使用 utf-8 编码的,怎么查看网页的编码方式呢?需要人为操作,且非常简单的方法是使用使用浏览器审查元素,只需要找到 head 标签开始位置的 chareset,就知道网页是采用何种编码的了。如下:

picture9

    这样我们就知道了这个网站的编码方式,但是这需要我们每次都打开浏览器,并找下编码方式,显然有些费事,使用几行代码解决更加省事并且显得酷一些。

 

自动获取网页编码方式的方法

    获取网页编码的方式有很多,个人更喜欢用第三方库的方式。

    首先我们需要安装第三方库 chardet,它是用来判断编码的模块,安装方法如下图所示,只需要输入指令:

pip install chardet

直接 cmd 命令行安装

下载是如果告知你要升级运行以下命令 python -m pip install --upgrade pip,升级 pip 版本。

 一下案例参考自:https://blog.csdn.net/csdn2497242041/article/details/77170746

例子 1 :爬取简书网站首页文章的标题和文章链接

首先配置现在第三方,

爬虫流程:①先由 urllib 的 request 打开 Url 得到网页 html 文档——②浏览器打开网页源代码分析元素节点——③通过 Beautiful Soup 或则正则表达式提取想要的数据——④存储数据到本地磁盘或数据库(抓取,分析,存储)

下载安装 pip install beautifulsoup4

 1 # spider
 2 # author_mark
 3 # -*- coding: UTF-8 -*-
 4 '''
 5 # Method 1
 6 import urllib.request
 7 
 8 url = "http://www.baidu.com"
 9 page_info = urllib.request.urlopen(url).read()
10 page_info = page_info.decode('utf-8')
11 print(page_info)
12 '''
13 
14 # Method 2
15 from urllib import request
16 from bs4 import BeautifulSoup
17 
18 url = 'http://www.jianshu.com'
19 # page = request.Request(url)
20 # page.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36')
21 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
22 page = request.Request(url, headers=headers)
23 page_info = request.urlopen(page).read().decode('utf-8')#打开 Url, 获取 HttpResponse 返回对象并读取其 ResposneBody
24 # print(page_info)
25 soup = BeautifulSoup(page_info, 'html.parser')
26 titles = soup.find_all('a', 'title')    # 查找所有 a 标签中 class='title' 的语句
27 '''
28 # 打印查找到的每一个 a 标签的 string 和文章链接
29 for title in titles:
30         print(title.string)
31         print("http://www.jianshu.com" + title.get('href'))
32 '''
33 # open()是读写文件的函数,with 语句会自动 close() 已打开文件
34 with open(r'D:\Only me\python-code-pycharm\test.txt', "w")as file:     #  在磁盘以只写的方式打开 / 创建一个名为 test 的 txt 文件
35     for title in titles:
36         file.write(title.string + '\n')
37         file.write("http://www.jianshu.com" + title.get('href') + '\n\n')
View Code

例子 2:爬取知乎网站的美女图片链接,并保存到本地

# -*- coding: UTF-8 -*-
from urllib import request
from bs4 import BeautifulSoup
import re
import time

url = "https://www.zhihu.com/question/22918070"
headers
= {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}
page
= request.Request(url, headers=headers)
html
= request.urlopen(page).read().decode('utf-8')
soup
= BeautifulSoup(html, 'html.parser')
# print("page")
#
用 Beautiful Soup 结合正则表达式来提取包含所有图片链接(img 标签中,class=**,以.jpg 结尾的链接)的语句
links = soup.find_all('img', "origin_image zh-lightbox-thumb", src=re.compile(r'.jpg$'))
print(links)
# 设置保存图片的路径,否则会保存到程序当前路径
path = r'D:\Only me\python-code-pycharm\pic' # 路径前的 r 是保持字符串原始值的意思,就是说不对其中的符号进行转义
for link in links:
print(link.attrs['src'])
# 保存链接并命名,time.time() 返回当前时间戳防止命名冲突
request.urlretrieve(link.attrs['src'], path+'%s.jpg' % time.time()) # 使用 request.urlretrieve 直接将所有远程链接数据下载到本地

 

 

 

 大概学习了下通过 urllib 和 Beautiful Soup 进行简单数据爬取的流程,但是那只适用于一些简单的、数据量比较小的爬虫项目,如果需要爬取的数据量比较大的话,之前的方法必定非常缓慢,而且还可能遇到大规模爬虫 IP 被网站封禁的情况,因为好的网站会有反爬虫策略。多线程和分布式爬虫、
IP 代理、处理验证码、模拟登陆、内置浏览器引擎爬虫,还有注意配合反爬虫措施比较少的移动 APP 端抓取(抓包工具 Fiddler)等等问题。考虑成熟框架 Scrapy。