Python 爬虫入门实战

1. 前言

首先自我介绍一下,我是一个作 Java 的开发人员,从今年下半年开始,一直在各大技术博客网站发表本身的一些技术文章,差很少有几个月了,以前在 cnblog 博客园加了网站统计代码,看到天天的访问量逐渐多了起来,国庆正好事情很少,就想着写一个爬虫,看下具体阅读量增长了多少,这也就成了本文的由来。html

2. 技术选型

爬虫这个功能,我我的理解是什么语言都能写的,只要能正常发送 HTTP 请求,将响应回来的静态页面模版 HTML 上把咱们所须要的数据提取出来就能够了,原理很简单,这个东西固然能够手动去统计收集,可是网络平台毕竟仍是不少的,仍是画点时间,写个爬虫把数据爬取下来,存到数据库里,而后写一个统计报表的 SQL 语句比较方便,后续若是有时间的话,我会写一个简单的先后端分离的报表样例分享出来。node

网上如今 Python 爬虫的课程很是的火爆,其实我内心也有点小九九,想玩点骚操做,不想用老本行去写这个爬虫,固然最后的事实是证实确实用 Python 写爬虫要比用 Java 来写爬虫要简单的多。python

3. 环境准备

首先笔者的电脑是 Win10 的,Python 选用的是 3.7.4 ,貌似如今网上 Python3 的爬虫教程并很少,其中仍是遇到很多的问题,下面也会分享给你们。mysql

开发工具笔者选用的是 VSCode ,在这里推荐一下微软这个开源的产品,很是的轻量化,须要什么插件本身安装就好,不用的插件一概不要,自主性很是高,若是感受搞不定的朋友能够选择 JetBrains 提供的 Pycharm ,分为社区版和付费版,通常而言,咱们使用社区版足矣。git

笔者这里直接新建了一个文件夹,建立了一个名为 spider-demo.py 的文件,这个就是咱们一会要写的爬虫的文件了,能够给你们看下笔者的开发环境,以下:github

这实际上是一个调试成功的截图,从下面打印的日志中能够看到,笔者这里抓取了三个平台的数据。sql

4. 数据库

笔者使用的数据是 Mysql 5.7.19 版本,数据库的字符集是使用的 utf8mb4 ,至于为何使用 utf8mb4 而不是 utf8 ,各位百度一下吧,不少人讲的都比我讲的好,我简单说一句就是 Mysql 的 utf8 实际上是一个假的 utf8 ,然后面增长的字符集 utf8mb4 才是真正的 utf8 。数据库

而 Python 链接 Mysql 也是须要驱动的,和在 Java 中链接数据库须要驱动同样,这里使用的是 pymysql ,安装命令:后端

pip install pymysql
复制代码

有没有感受很简单, pip 是 Python 的一个包管理工具,个人我的理解是相似于一个 Maven 的东西,全部的咱们须要的第三方的包都能在这个上面下载到。浏览器

固然,这里可能会出现 timeout 的状况,视你们的网络状况而定,我在晚上执行这个命令的时候真的是各类 timeout ,固然 Maven 会有国内的镜像战, pip 显然确定也会有么,这里都列给你们:

具体使用方式命令以下:

pip install -i https://mirrors.aliyun.com/pypi/simple/ 库名
复制代码

笔者这里仅仅尝试过阿里云和清华大学的镜像站,其他未作尝试,以上内容来自于网络。

表结构,设计以下图,这里设计很粗糙的,简简单单的只作了一张表,多余话我也不说,你们看图吧,字段后面都有注释了:

建表语句提交至 Github 仓库,有须要的同窗能够去查看。

5. 实战

总体思路分如下这么几步:

  1. 经过 GET 请求将整个页面的 HTML 静态资源请求回来
  2. 经过一些匹配规则匹配到咱们须要的数据
  3. 存入数据库

5.1 请求 HTML 静态资源

Python3 为咱们提供了 urllib 这个标准库,无需咱们额外的安装,使用的时候须要先引入:

from urllib import request
复制代码

接下来咱们使用 urllib 发送 GET 请求,以下:

req_csdn = request.Request('https://blog.csdn.net/meteor_93')
req_csdn.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36')
html_csdn = request.urlopen(req_csdn).read().decode('utf-8')
复制代码

User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器可以识别客户使用的操做系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

这里在请求头中添加这个是为了模拟浏览器正常请求,不少服务器都会作检测,发现不是正常浏览器的请求会直接拒绝,虽而后面实测笔者爬取的这几个平台都没有这项检测,可是能加就加一下么,固然真实的浏览器发送的请求头里面不只仅只有一个 UA ,还会有一些其余的信息,以下图:

笔者这里的 UA 信息是直接从这里 Copy 出来的。代码写到这里,咱们已经拿到了页面静态资源 html_csdn ,接下来咱们就是要解析这个资源,从中匹配出来咱们须要的信息。

5.2 xpath 数据匹配

xpath 是什么?

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。 XPath 是 W3C XSLT 标准的主要元素,而且 XQuery 和 XPointer 都构建于 XPath 表达之上。

从上面这句话咱们能够看出来, xpath 是用来查找 XML ,而咱们的 HTML 能够认为是语法不标准的 XML 文档,恰巧咱们能够经过这种方式来解析 HTML 文档。

咱们在使用 xpath 以前,须要先安装 xpath 的依赖库,这个库并非 Python 提供的标准库,安装语句以下:

pip install lxml
复制代码

若是网络不给力的同窗可使用上面的镜像站进行安装。

而 xpath 的表达式很是简单,具体的语法你们能够参考 W3school 提供的教程(www.w3school.com.cn/xpath/xpath… ),笔者这里很少介绍,具体使用方式以下:

read_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[3]/dl[2]/dd/@title')[0]
fans_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="fan"]/text()')[0]
rank_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[3]/dl[4]/@title')[0]
like_num_csdn = etree.HTML(html_csdn).xpath('//*[@id="asideProfile"]/div[2]/dl[3]/dd/span/text()')[0]
复制代码

这里笔者主要获取了总阅读数、总粉丝数、排名和总点赞数。

这里列举几个最基础的使用,这几个使用在本示例中已经彻底够用:

表达式 描述
nodename 选取此节点的全部子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
text 选取当前节点内容。

还有一种简单的方式,咱们能够经过 Chrome 浏览器获取 xpath 表达式,具体操做见截图:

打开 F12 ,鼠标右键须要生成 xpath 表达式的内容,点击 Copy -> Copy XPath 便可。

这里有一点须要注意,咱们直接经过 xpath 取出来的数据数据类型并非基础数据类型,若是要作运算或者字符串拼接,须要作类型强转,不然会报错,以下:

req_cnblog = request.Request('https://www.cnblogs.com/babycomeon/default.html?page=2')
req_cnblog.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36')
html_cnblog = request.urlopen(req_cnblog).read().decode('utf-8')

max_page_num = etree.HTML(html_cnblog).xpath('//*[@id="homepage_top_pager"]/div/text()')

# 最大页数
max_page_num = re.findall(r"\d+\.?\d*", str(max_page_num))[0]
复制代码

这里须要获取 cnblog 的博客最大页数,首先取到了 max_page_num ,这里直接作 print 的话是能够正常打印一个字符串出来的,可是若是直接去作正则匹配,就会类型错误。

5.3 写入数据库

数据库的操做我就很少作介绍了,有写过 Java 的同窗应该都很清楚 jdbc 是怎么写的,先使用 ip 、 port 、 用户名、密码、数据库名称、字符集等信息获取链接,而后开启链接,写一句 sql ,把 sql 拼好,执行 sql ,而后提交数据,而后关闭链接,代码以下:

def connect():
    conn = pymysql.connect(host='localhost',
                           port=3306,
                           user='root',
                           password='123456',
                           database='test',
                           charset='utf8mb4')

    # 获取操做游标
    cursor = conn.cursor()
    return {"conn": conn, "cursor": cursor}

connection = connect()
conn, cursor = connection['conn'], connection['cursor']

sql_insert = "insert into spider_data(id, plantform, read_num, fans_num, rank_num, like_num, create_date) values (UUID(), %(plantform)s, %(read_num)s, %(fans_num)s, %(rank_num)s, %(like_num)s, now())"

复制代码

在本示例中,爬虫只负责一个数据爬取工做,因此只须要一句 insert 语句就够了,而后在每一个平台爬取完成后,将这句 sql 中的占位符替换掉,执行 sql 后 commit 操做便可,示例代码以下:

csdn_data = {
    "plantform": 'csdn',
    "read_num": read_num_csdn,
    "fans_num": fans_num_csdn,
    "rank_num": rank_num_csdn,
    "like_num": like_num_csdn
}

cursor.execute(sql_insert, csdn_data)
conn.commit()
复制代码

6. 小结

通过这么一次 Python 爬虫的实际体验后,确实感受使用 Python 写程序语法很是的简单,总体程序使用 130+ 行,大体估算一下,若是使用 Java 书写一样的功能,可能会须要 200+ 行,使用 httpClient 发送 GET 请求再解析响应就不是这么 Python 这种简简单单的 2~3 行代码搞的定的。本示例的爬虫其实还很是的不完善,目前只能爬取不须要登陆的平台的数据,有的平台须要登陆后才能看到统计数据,这就要和 Cookies 相结合才能完成模拟登录的过程。后续有空我会接着完善这只小爬虫的。

本次的 Python 爬虫更多的相似于一个技术尝鲜,其中大量的代码都是经过搜索引擎得到,其中的写法有些懵懵懂懂,笔者决定后续系统的学习一下 Python ,届时会分享一些学习过程出来,有兴趣的小伙伴能够跟着笔者一块儿学习、讨论。

老规矩,本篇的代码也提交至 Github 仓库和 Gitee 仓库,有须要的朋友能够自行索取,仓库命名为 python-learn ,也算是对本身学习的一种监督吧,每次学习的示例代码都会提交至这个仓库。

7. 示例代码

示例代码-Github

示例代码-Gitee

8. 参考:

XPath 教程

相关文章
相关标签/搜索