2022 年 Python3 网络爬虫教程
大家好,我是崔庆才,由于爬虫技术不断迭代升级,一些旧的教程已经过时、案例已经过期,最前沿的爬虫技术比如异步、JavaScript 逆向、安卓逆向、智能解析、WebAssembly、大规模分布式、Kubernetes 等技术层出不穷,我最近新出了一套最新最全面的 Python3 网络爬虫系列教程。
博主自荐:截止 2022 年,可以将最前沿最全面的爬虫技术都涵盖的教程,如异步、JavaScript 逆向、安卓逆向、智能解析、WebAssembly、大规模分布式、Kubernetes 等,市面上目前就这一套了。
最新教程对旧的爬虫技术内容进行了全面更新,搭建了全新的案例平台进行全面讲解,保证案例稳定有效不过期。
教程请移步:
2018 年 Python3 爬虫系列教程
以下为 2018 年版 Python3 网络爬虫系列教程
本内容来自于《Python3 网络爬虫开发实战》一书。 书籍购买地址: https://item.jd.com/12333540.html
本书通过多个实战案例详细介绍了 Python3 网络爬虫的知识,本书由图灵教育-人民邮电出版社出版发行,版权所有,禁止转载。
- 1-开发环境配置
- 1.1-Python3 的安装
- 1.2-请求库的安装
- 1.2.1-Requests 的安装
- 1.2.2-Selenium 的安装
- 1.2.3-ChromeDriver 的安装
- 1.2.4-GeckoDriver 的安装
- 1.2.5-PhantomJS 的安装
- 1.2.6-aiohttp 的安装
- 1.3-解析库的安装
- 1.3.1-lxml 的安装
- 1.3.2-Beautiful Soup 的安装
- 1.3.3-pyquery 的安装
- 1.3.4-tesserocr 的安装
- 1.4-数据库的安装
- 1.4.1-MySQL 的安装
- 1.4.2-MongoDB 安装
- 1.4.3-Redis 的安装
- 1.5-存储库的安装
- 1.5.1-PyMySQL 的安装
- 1.5.2-PyMongo 的安装
- 1.5.3-redis-py 的安装
- 1.5.4-RedisDump 的安装
- 1.6-Web 库的安装
- 1.6.1-Flask 的安装
- 1.6.2-Tornado 的安装
- 1.7-App 爬取相关库的安装
- 1.7.1-Charles 的安装
- 1.7.2-mitmproxy 的安装
- 1.7.3-Appium 的安装
- 1.8-爬虫框架的安装
- 1.8.1-pyspider 的安装
- 1.8.2-Scrapy 的安装
- 1.8.3-Scrapy-Splash 的安装
- 1.8.4-Scrapy-Redis 的安装
- 1.9-部署相关库的安装
- 1.9.1-Docker 的安装
- 1.9.2-Scrapyd 的安装
- 1.9.3-Scrapyd-Client 的安装
- 1.9.4-Scrapyd API 的安装
- 1.9.5-Scrapyrt 的安装
- 1.9.6-Gerapy 的安装
- 2-爬虫基础
- 2.1-HTTP 基本原理
- 2.2-网页基础
- 2.3-爬虫的基本原理
- 2.4-会话和 Cookies
- 2.5-代理的基本原理
- 3-基本库的使用
- 3.1-使用 urllib
- 3.1.1-发送请求
- 3.1.2-处理异常
- 3.1.3-解析链接
- 3.1.4-分析 Robots 协议
- 3.2-使用 requests
- 3.2.1-基本用法
- 3.2.2-高级用法
- 3.3-正则表达式
- 3.4-抓取猫眼电影排行
- 4-解析库的使用
- 4.1-使用 XPath
- 4.2-使用 Beautiful Soup
- 4.3-使用 pyquery
- 5-数据存储
- 5.1-文件存储
- 5.1.1-TXT 文本存储
- 5.1.2-JSON 文件存储
- 5.1.3-CSV 文件存储
- 5.2-关系型数据库存储
- 5.2.1-MySQL 存储
- 5.3-非关系型数据库存储
- 5.3.1-MongoDB 存储
- 5.3.2-Redis 存储
- 6-Ajax 数据爬取
- 6.1-什么是 Ajax
- 6.2-Ajax 分析方法
- 6.3-Ajax 结果提取
- 6.4-分析 Ajax 爬取今日头条街拍美图
- 7-动态渲染页面爬取
- 7.1-Selenium 的使用
- 7.2-Splash 的使用
- 7.3-Splash 负载均衡配置
- 7.4-使用 Selenium 爬取淘宝商品
- 8-验证码的识别
- 8.1-图形验证码的识别
- 8.2-极验滑动验证码的识别
- 8.3-点触验证码的识别
- 8.4-微博宫格验证码的识别
- 9-代理的使用
- 9.1-代理的设置
- 9.2-代理池的维护
- 9.3-付费代理的使用
- 9.4-ADSL 拨号代理
- 9.5-使用代理爬取微信公众号文章
- 10-模拟登录
- 10.1-模拟登录并爬取 GitHub
- 10.2-Cookies 池的搭建
- 11-App 的爬取
- 11.1-Charles 的使用
- 11.2-mitmproxy 的使用
- 11.3-mitmdump 爬取“得到”App 电子书信息
- 11.4-Appium 的基本使用
- 11.5-Appium 爬取微信朋友圈
- 11.6-Appium+mitmdump 爬取京东商品
- 12-pyspider 框架的使用
- 12.1-pyspider 框架介绍
- 12.2-pyspider 的基本使用
- 12.3-pyspider 用法详解
- 13-Scrapy 框架的使用
- 13.1-Scrapy 框架介绍
- 13.2-Scrapy 入门
- 13.3-Selector 的用法
- 13.4-Spider 的用法
- 13.5-Downloader Middleware 的用法
- 13.6-Spider Middleware 的用法
- 13.7-Item Pipeline 的用法
- 13.8-Scrapy 对接 Selenium
- 13.9-Scrapy 对接 Splash
- 13.10-Scrapy 通用爬虫
- 13.11-Scrapyrt 的使用
- 13.12-Scrapy 对接 Docker
- 13.13-Scrapy 爬取新浪微博
- 14-分布式爬虫
- 14.1-分布式爬虫原理
- 14.2-Scrapy-Redis 源码解析
- 14.3-Scrapy 分布式实现
- 14.4-Bloom Filter 的对接
- 15-分布式爬虫的部署
- 15.1-Scrapyd 分布式部署
- 15.2-Scrapyd-Client 的使用
- 15.3-Scrapyd 对接 Docker
- 15.4-Scrapyd 批量部署
- 15.5-Gerapy 分布式管理





接下来按照大才的文章,pip install gerapy 即可,这一步没有遇到什么问题。有问题的同学可以向大才提 issue。
然后到命令窗口对 8000 和 6800 端口放行即可。 接着执行
里面的各个的含义见大才的文章。
后来找了一下原因发现 scrapyd 默认打开的也是 127.0.0.1
所以这个时候就要改一下配置,具体可以参考

可以看到输出的结果了。
如图所示为 Bi-LSTM 的基本原理,输入层的数据会经过向前和向后两个方向推算,最后输出的隐含状态再进行 concat,再作为下一层的输入,原理其实和 LSTM 是类似的,就是多了双向计算和 concat 过程。
接下来我们在浏览器中打开
这里显示了主机、项目的状态,当然由于我们没有添加主机,所以所有的数目都是 0。 如果我们可以正常访问这个页面,那就证明 Gerapy 初始化都成功了。
需要添加 IP、端口,以及名称,点击创建即可完成添加,点击返回即可看到当前添加的 Scrapyd 服务列表,样例如下所示:
这样我们可以在状态一栏看到各个 Scrapyd 服务是否可用,同时可以一目了然当前所有 Scrapyd 服务列表,另外我们还可以自由地进行编辑和删除。
假设现在我们有一个 Scrapy 项目,如果我们想要进行管理和部署,还记得初始化过程中提到的 projects 文件夹吗?这时我们只需要将项目拖动到刚才 gerapy 运行目录的 projects 文件夹下,例如我这里写好了一个 Scrapy 项目,名字叫做 zhihusite,这时把它拖动到 projects 文件夹下:
这时刷新页面,我们便可以看到 Gerapy 检测到了这个项目,同时它是不可配置、没有打包的:
这时我们可以点击部署按钮进行打包和部署,在右下角我们可以输入打包时的描述信息,类似于 Git 的 commit 信息,然后点击打包按钮,即可发现 Gerapy 会提示打包成功,同时在左侧显示打包的结果和打包名称:
打包成功之后,我们便可以进行部署了,我们可以选择需要部署的主机,点击后方的部署按钮进行部署,同时也可以批量选择主机进行部署,示例如下:
可以发现此方法相比 Scrapyd-Client 的命令行式部署,简直不能方便更多。
我们可以通过点击新任务、停止等按钮来实现任务的启动和停止等操作,同时也可以通过展开任务条目查看日志详情:
另外我们还可以随时点击停止按钮来取消 Scrapy 任务的运行。 这样我们就可以在此页面方便地管理每个 Scrapyd 服务上的 每个 Scrapy 项目的运行了。
这样即使 Gerapy 部署在远程的服务器上,我们不方便用 IDE 打开,也不喜欢用 Vim 等编辑软件,我们可以借助于本功能方便地完成代码的编写。
再比如爬取规则,我们可以指定从哪个链接开始爬取,允许爬取的域名是什么,该链接提取哪些跟进的链接,用什么解析方法来处理等等配置。通过这些配置,我们可以完成爬取规则的设置。
最后点击生成按钮即可完成代码的生成。
生成的代码示例结果如图所示,可见其结构和 Scrapy 代码是完全一致的。
生成代码之后,我们只需要像上述流程一样,把项目进行部署、启动就好了,不需要我们写任何一行代码,即可完成爬虫的编写、部署、控制、监测。
在上图网络结构中,对于矩形块 A 的那部分,通过输入xt(t时刻的特征向量),它会输出一个结果ht(t时刻的状态或者输出)。网络中的循环结构使得某个时刻的状态能够传到下一个时刻。 这些循环的结构让 RNNs 看起来有些难以理解,但我们可以把 RNNs 看成是一个普通的网络做了多次复制后叠加在一起组成的,每一网络会把它的输出传递到下一个网络中。我们可以把 RNNs 在时间步上进行展开,就得到下图这样:
所以最基本的 RNN Cell 输入就是 xt,它还会输出一个隐含内容传递到下一个 Cell,同时还会生成一个结果 ht,其最基本的结构如如下:
仅仅是输入的 xt 和隐藏状态进行 concat,然后经过线性变换后经过一个 tanh 激活函数便输出了,另外隐含内容和输出结果是相同的内容。 我们来分析一下 TensorFlow 里面 RNN Cell 的实现。 TensorFlow 实现 RNN Cell 的位置在 python/ops/rnncellimpl.py,首先其实现了一个 RNNCell 类,继承了 Layer 类,其内部有三个比较重要的方法,state_size()、output_size()、__call() 方法,其中 state_size() 和 output_size() 方法设置为类属性,可以当做属性来调用,实现如下:
但是如果我们想依赖前文距离非常远的信息时,普通的 RNN 就非常难以做到了,随着间隔信息的增大,RNN 难以对其做关联:
但是 LSTM 可以用来解决这个问题。 LSTM,Long Short Term Memory Networks,是 RNN 的一个变种,经试验它可以用来解决更多问题,并取得了非常好的效果。 LSTM Cell 的结构如下:
LSTMs 最关键的地方在于 Cell 的状态 和 结构图上面的那条横穿的水平线。 Cell 状态的传输就像一条传送带,向量从整个 Cell 中穿过,只是做了少量的线性操作。这种结构能够很轻松地实现信息从整个 Cell 中穿过而不做改变。
若只有上面的那条水平线是没办法实现添加或者删除信息的,信息的操作是是通过一种叫做门的结构来实现的。 这里我们可以把门分为三个:遗忘门(Forget Gate)、传入门(Input Gate)、输出门(Output Gate)。
在经过 Forget Gate 和 Input Gate 处理后,我们就可以对输入的 Ct-1 做更新了,即把Ct−1 更新为 Ct,首先我们把旧的状态 Ct−1 和 ft 相乘, 把一些不想保留的信息忘掉。然后加上 it∗Ct~,这部分信息就是我们要添加的新内容,这样就可以完成对 Ct-1 的更新。 
到了最后,其输出结果有三个内容,其中输出结果就是最上面的箭头代指的内容,即最终计算的结果,隐层包括两部分内容,一个是 Ct,一个是最下方的 ht,我们可以将其合并为一个变量来表示。 接下来我们来看下 LSTMCell 的 TensorFlow 代码实现。 首先它的类是 BasicLSTMCell 类,继承了 RNNCell 类,其初始化方法 init() 实现如下:
另外还有一个变种就是将 Forget Gate 和 Input Gate 二者联合起来,做到要么遗忘老的输入新的,要么保留老的不输入新的。
但接下来还有一个更常用的变种,俺就是 GRU,它是由 Cho, et al. (2014) 提出的,在提出的同时他还提出了 Seq2Seq 模型,为 Generation Model 做好了铺垫。
接下来我们看下 TensorFlow 中 GRUCell 的实现,代码如下:
数据集中包含了图片和对应的标注,在 TensorFlow 中提供了这个数据集,我们可以用如下方法进行导入:
正如前面提到的一样,每一个 MNIST 数据单元有两部分组成:一张包含手写数字的图片和一个对应的标签。我们把这些图片设为 xs,把这些标签设为 ys。训练数据集和测试数据集都包含 xs 和 ys,比如训练数据集的图片是 mnist.train.images ,训练数据集的标签是 mnist.train.labels,每张图片是 28 x 28 像素,即 784 个像素点,我们可以把它展开形成一个向量,即长度为 784 的向量。 所以训练集我们可以转化为 [55000, 784] 的向量,第一维就是训练集中包含的图片个数,第二维是图片的像素点表示的向量。
展开等式右边的子式,可以得到:
比如判断一张图片中的动物是什么,可能的结果有三种,猫、狗、鸡,假如我们可以经过计算得出它们分别的得分为 3.2、5.1、-1.7,Softmax 的过程首先会对各个值进行次幂计算,分别为 24.5、164.0、0.18,然后计算各个次幂结果占总次幂结果的比重,这样就可以得到 0.13、0.87、0.00 这三个数值,所以这样我们就可以实现差别的放缩,即好的更好、差的更差。 如果要进一步求损失值可以进一步求对数然后取负值,这样 Softmax 后的值如果值越接近 1,那么得到的值越小,即损失越小,如果越远离 1,那么得到的值越大。
这里实际上是对输入的 x 乘以 w 权重,然后加上一个偏置项作为输出,而这两个变量实际是在训练的过程中动态调优的,所以我们需要指定它们的类型为 Variable,代码如下:
y 是我们预测的概率分布, y_label 是实际的分布,比较粗糙的理解是,交叉熵是用来衡量我们的预测用于描述真相的低效性。 我们可以首先定义 y_label,它的表达式是:










另外我们也可以单独添加单个 Node 或 Relationship,实例如下:
另外还可以利用 data() 方法来获取查询结果:
在这里我们用 NodeSelector 来筛选 age 为 21 的 Person Node,实例如下:

























在这里推荐安装CentOS7系统。 然后找到远程管理面板找到远程连接的用户名和密码,也就是SSH远程连接服务器的信息。 比如我这边的IP端口分别是 153.36.65.214:20063,用户名是root。 命令行下输入:
都提示成功之后就可以进行拨号了。 在拨号之前如果我们测试ping任何网站都是不通的,因为当前网络还没联通,输入拨号命令:
所以断线重播的命令就是二者组合起来,先执行
所以,到这里我们就可以知道它作为代理服务器的巨大优势了,如果将这台主机作为代理服务器,如果我们一直拨号换IP,就不怕遇到IP被封的情况了,即使某个IP被封了,重新拨一次号就好了。 所以接下来我们要做的就有两件事,一是怎样将主机设置为代理服务器,二是怎样实时获取拨号主机的IP。
如果有正常的结果输出并且origin的值为代理IP的地址,就证明TinyProxy配置成功了。 好,那到现在,我们接下来要做的就是需要动态实时获取主机的IP了。
获取最新代理:
获取所有代理:
请求接口获取可用代理即可,比如获取一个随机代理:















我们可以看到这里就是他的一些基本信息,我们需要抓取的就是这些,比如名字、签名、职业、关注数、赞同数等等。 接下来我们需要探索一下关注列表接口在哪里,我们点击关注选项卡,然后下拉,点击翻页,我们会在下面的请求中发现出现了 followees开头的Ajax请求。这个就是获取关注列表的接口。
我们观察一下这个请求结构
首先它是一个Get类型的请求,请求的URL是
可以看到有data和paging两个字段,data就是数据,包含20个内容,这些就是用户的基本信息,也就是关注列表的用户信息。 paging里面又有几个字段,is_end表示当前翻页是否结束,next是下一页的链接,所以在判读分页的时候,我们可以先利用is_end判断翻页是否结束,然后再获取next链接,请求下一页。 这样我们的关注列表就可以通过接口获取到了。 接下来我们再看下用户详情接口在哪里,我们将鼠标放到关注列表任意一个头像上面,观察下网络请求,可以发现又会出现一个Ajax请求。
可以看到这次的请求链接为
所以综上所述:
可以看到返回的结果非常全,在这里我们直接声明一个Item全保存下就好了。 在items里新声明一个UserItem
看下MongoDB,里面我们爬取的用户详情结果。
到现在为止,整个爬虫就基本完结了,我们主要通过递归的方式实现了这个逻辑。存储结果也通过适当的方法实现了去重。
























