本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理

以下文章来源于腾讯云 作者:程序员宝库

**( 想要学习Python?Python学习交流群:1039649593,满足你的需求,资料都已经上传群文件流,可以自行下载!还有海量最新2020python学习资料。 )**

遇到的需求

前段时间需要快速做个静态展示页面,要求是响应式和较美观。由于时间较短,自己动手写的话也有点麻烦,所以就打算上网找现成的。

中途找到了几个页面发现不错,然后就开始思考怎么把页面给下载下来。

由于之前还没有了解过爬虫,自然也就没有想到可以用爬虫来抓取网页内容。所以我采取的办法是:

打开chrome的控制台,进入Application选项

找到Frames选项,找到html文件,再右键Save As…

手动创建本地的js/css/images目录

依次打开Frames选项下的Images/Scripts/Stylesheets,一个文件就要右键Save As…

这个办法是我当时能想到的最好办法了。不过这种人为的办法有以下缺点:

手工操作,麻烦费时

一不小心就忘记保存哪个文件

难以处理路径之间的关系,比如一张图片a.jpg, 它在html中的引用方式是images/banner/a.jpg,这样我们以后还要手动去解决路径依赖关系然后刚好前段时间接触了一点python,想到可以写个python爬虫来帮我自动抓取静态网站。于是就马上动手,参考相关资料等等。

下面跟大家详细分享一下写爬虫抓取静态网站的全过程。

前置知识储备

在下面的代码实践中,用到了python知识、正则表达式等等,核心技术是正则表达式。

我们来一一了解一下。

Python基础知识

如果你之前有过其他语言的学习经历,相信你可以很快上手python这门语言。具体学习可以上查看python官方文档或者其他教程。

爬虫的概念

爬虫,按照我的理解,其实是一段自动执行的计算机程序,在web领域中,它存在的前提是模拟用户在浏览器中的行为。

它的原理就是模拟用户访问web网页,获取网页内容,然后分析网页内容,找出我们感兴趣的部分,并且最后处理数据。

流程图是:

现在流行的爬虫主流实现形式有以下几种:

1.自己抓取网页内容,然后自己实现分析过程

2.用别人写好的爬虫框架,比如Scrapy

正则表达式

概念

正则表达式是由一系列元字符和普通字符组成的字符串,它的作用是根据一定的规则来匹配文本,最终可以对文本做出一系列的处理。

元字符是正则表达式中的保留字符,它有特殊的匹配规则,比如*代表匹配0到无穷多次,普通字符就是普通的abcd等等。

比如在前端中,常见的一个操作就是判断用户的输入是否为空,这时候我们可以先通过正则表达式来进行匹配,先过滤掉用户输入的两边空白值,具体实现如下:

function trim(value) {return value.replace(/^s+|s+$/g, '')

}// 输出 => "Python爬虫"trim('Python爬虫');

下面我们一起来具体了解一下正则表达式中的元字符。

正则表达式中的元字符

在上面,我们说过元字符是正则表达式中的保留字符,它有特殊的匹配规则,所以我们首先要了解经常出现的元字符。

匹配单个字符的元字符

代表匹配一个任意字符,除了(换行符),比如可以匹配任意的字母数字等等

[…]表示字符组,里面可以有任意字符,它只会匹配当中的任意一个,比如[abc]可以匹配a或b或c,这里值得注意的是,字符组里面的元字符有时候会被当成是普通字符,比如[-?]等等,它代表的仅仅是-或或?,而不是-代表区间,*代表0到无穷次匹配,?代表0或1次匹配。

[^…]跟[…]的含义相反,它的意思是匹配一个不属于[…]里面的字符,而不是不匹配[…]里面的字符,这两种说法虽然细微但是有很大差别,前者规定一定要匹配一个字符,这个切记。

例子:[^123]可以匹配4/5/6等等,但是不匹配1/2/3

提供计数功能的元字符

*代表匹配0次到无穷次,可以不匹配任何字符

+代表匹配1次到无穷次,至少匹配1次

?代表匹配0次或1次

{min, max}代表匹配min次到max次,如a{3, 5}表示a至少匹配3-5次

提供位置的元字符

^ 代表匹配字符串开头,如^a表示a要出现在字符串开头,bcd则不匹配

$ 代表匹配字符串结尾, 如A$表示A要出现在字符串结尾,ABAB则不匹配

其他元字符

|代表一个范围,可以匹配任意的子表达式,比如abc|def可以匹配abc或者def,不匹配abd

(…)代表分组,它的作用有界定子表达式的范围和与提供功能的元字符相结合,比如(abc|def)+代表可以匹配1次或1次以上的abc或者defdef,如abcabcabc,def

i代表反向引用,i可以为1/2/3等整数,它的含义是指向上一个()里面匹配的内容。比如匹配(abc)+(12)*,如果匹配成功的话,的内容是abc,的内容是12或者空。反向引用通常用在匹配""或者’'中

环视

我理解的环视是界定当前匹配子表达式的左边文本和右边文本出现的情况,环视本身不会占据匹配的字符,它是当前子表达式的匹配规则但是本身不算进匹配文本。而我们上面说的元字符都代表一定的规则和占据一定的字符。

环视可分为四种:肯定顺序环视、否定顺序环视、肯定逆序环视和否定逆序环视。它们的工作流程如下:

肯定顺序环视:先找到环视中的文本在右侧出现的初始位置,然后从匹配到的右侧文本的最左的位置开始匹配字符

否定顺序环视:先找到环视中的文本在右侧没有出现的初始位置,然后从匹配到的右侧文本的最左的位置开始匹配字符

肯定逆序环视:先找到环视中的文本在左侧出现的初始位置,然后从匹配到的左侧文本的最右的位置开始匹配字符

否定逆序环视:先找到环视中的文本在左侧没有出现的初始位置,然后从匹配到的左侧文本的最右的位置开始匹配字符

肯定顺序环视

肯定顺序环视匹配成功的条件是当前的子表达式能够匹配右侧文本,它的写法是(?=…),…代表要环视的内容。比如正则表达式(?=hello)he的意思是匹配包含hello的文本,它只匹配位置,不匹配具体字符,匹配到位置之后,才真正匹配要占用的字符是he,所以后面可以具体匹配llo等。

对于(?=hello)he而言,hello world可以匹配成功,而hell world则匹配失败。具体代码如下:

importre

reg1= r'(?=hello)he'

print(re.search(reg1, 'hello world'))print(re.search(reg1, 'hell world hello'))print(re.search(reg1, 'hell world'))#输出结果

<_sre.sre_match object span="(11," match="he">None

否定顺序环视

否定顺序环视匹配成功的条件是当前的子表达式不能匹配右侧文本,它的写法是(?!..),…代表要环视的内容,还是上面的例子,比如正则表达式(?!hello)he的意思是匹配不是hello的文本,找到位置,然后匹配he。

例子如下:

importre

reg2= r'(?!hello)he'

print(re.search(reg2, 'hello world'))print(re.search(reg2, 'hell world hello'))print(re.search(reg2, 'hell world'))#输出结果

None<_sre.sre_match object span="(0," match="he">

肯定逆序环视

肯定逆序环视匹配成功的条件是当前的子表达式能够匹配左侧文本,它的写法是(?<=…),…代表要环视的内容,比如正则表达式(?<=hello)-python的意思是匹配包含-python的子表达式,并且它的左侧必须出现hello,hello只匹配位置,不匹配具体字符,真正占用的字符是后面的-python。

例子如下:

importre

reg3= r'(?<=hello)-python'

print(re.search(reg3, 'hello-python'))print(re.search(reg3, 'hell-python hello-python'))print(re.search(reg3, 'hell-python'))#输出结果

<_sre.sre_match object span="(17," match="-python">None

否定逆序环视

否定逆序环视匹配成功的条件是当前的子表达式不能匹配左侧文本,它的写法是(?

例子如下:

importre

reg3= r'(?<=hello)-python'

print(re.search(reg3, 'hello-python'))print(re.search(reg3, 'hell-python hello-python'))print(re.search(reg3, 'hell-python'))#输出结果

环视在对字符串插入某些字符很有效,你可以利用它来匹配位置,然后插入对应的字符,而不需要对原来的文本进行替换。

捕获分组

在正则表达式中,分组可以帮助我们提取出想要的特定信息。

指明分组很简单,只需要在想捕获的表达式中两端加上()就可以了。在python中,我们可以用re.search(reg, xx).groups()来获取到所有的分组。

默认的()中都指明了一个分组,分组序号为i,i从1开始,分别用re.search(reg, xx).group(i)来获取。

如果不想捕获分组可以使用(?:…)来指明。

具体例子如下:

importre

reg7= r'hello,([a-zA-Z0-9]+)'

print(re.search(reg7, 'hello,world').groups())print(re.search(reg7, 'hello,world').group(1))print(re.search(reg7, 'hello,python').groups())print(re.search(reg7, 'hello,python').group(1))#输出结果

('world',)

world

('python',)

python

贪婪匹配

贪婪匹配是指正则表达式尽可能匹配多的字符,也就是趋于最大长度匹配。

正则表达式默认是贪婪模式。

例子如下:

importre

reg5= r'hello.*world'

print(re.search(reg5, 'hello world,hello python,hello world,hello javascript'))#输出结果

由上可以看到它匹配的是hello world,hello python,hello world而不是刚开始的hello world。那如果我们只是想匹配刚开始的hello world,这时候我们可以利用正则表达式的非贪婪模式。

非贪婪匹配正好与贪婪匹配相反,它是指尽可能匹配少的字符,只要匹配到了就结束。要使用贪婪模式,仅需要在量词后面加上一个问号(?)就可以。

还是刚刚那个例子:

importre

reg5= r'hello.*world'reg6= r'hello.*?world'

print(re.search(reg5, 'hello world,hello python,hello world,hello javascript'))print(re.search(reg6, 'hello world,hello python,hello world,hello javascript'))#输出结果

由上可以看到这是我们刚刚想要匹配的效果。

python爬虫资源大全_Python爬虫抓取纯静态网站及其资源(基础篇)相关推荐

  1. python爬虫知识大全_Python爬虫入门有哪些基础知识点

    1.什么是爬虫 爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来.想抓取什么?这个由你来控制它咯. ...

  2. python爬虫知识大全_Python爬虫知识点一

    一.入门知识: 1.1.HTTP简介 HTTP = HyperText Transfer Protocol URI = Uniform Resource Identifier URL = Unifor ...

  3. python爬虫教程大全_python爬虫入门教程

    爬虫是一个是一个好玩的技术,偷偷爬取mm的照片,爬取知乎用户头像等等,这些教程经验帖在网上随便一搜,到处都是:那么今天小编将给大家简单讲讲python爬虫的入门.鉴于经验排版模式有限,所以这里只能简单 ...

  4. JAVA爬虫进阶之springboot+webmagic抓取顶点小说网站小说

    闲来无事最近写了一个全新的爬虫框架WebMagic整合springboot的爬虫程序,不清楚WebMagic的童鞋可以先查看官网了解什么是Webmagic,顺便说说用springboot时遇到的一些坑 ...

  5. python request url 转义_Python多线程抓取Google搜索链接网页

    1)urllib2+BeautifulSoup抓取Goolge搜索链接 近期,参与的项目需要对Google搜索结果进行处理,之前学习了Python处理网页相关的工具.实际应用中,使用了urllib2和 ...

  6. python selenium 处理弹窗_python+selenium 抓取弹出对话框信息

    抓取弹出对话框信息,困挠了我很久,我百度了很久,一直没有找到我想要的内容.最近学习到了. 有两种方法: 1.driver.switch_to.alert.text 2.result = EC.aler ...

  7. python 弹出对话框_python+selenium 抓取弹出对话框信息

    抓取弹出对话框信息,困挠了我很久,我百度了很久,一直没有找到我想要的内容.最近学习到了. 有两种方法: 1.driver.switch_to.alert.text 2.result = EC.aler ...

  8. python个人网站系统_利用基于Python的Pelican打造一个自己的个人纯静态网站

    其实呢这么多年以来我一直建议每个有技术追求的开发者都要有写技术博客记笔记的良好习惯,一来可以积累知识,二来可以帮助别人,三来可以把开发中遇到的问题记录用来自省,第四可以通过交换友链来结识更多的技术领域 ...

  9. 利用基于Python的Pelican打造一个自己的个人纯静态网站

    其实呢这么多年以来我一直建议每个有技术追求的开发者都要有写技术博客记笔记的良好习惯,一来可以积累知识,二来可以帮助别人,三来可以把开发中遇到的问题记录用来自省,第四可以通过交换友链来结识更多的技术领域 ...

最新文章

  1. C#反射使用时注意BindingFlags的用法(转载)
  2. 1357篇ECCV 2020论文打包下载!奖项公布:李飞飞高徒获最佳论文奖
  3. 函数 php_PHP函数缺陷详解
  4. 【干货】智能电视UI设计那些事儿
  5. [Swift]LeetCode781. 森林中的兔子 | Rabbits in Forest
  6. Java期末复习——ch02基本类型(进制转换,数据类型转换,汉字编码)
  7. mysql 给指定用户指定数据库
  8. 为什么深层神经网络难以训练_“用魔法击败魔法”?一群计算神经学家正借神经网络解释大脑...
  9. arcgis python 教程-终于晓得arcgis-python入门教程
  10. 如何高效地学习机器学习算法?
  11. 一个GUI程序究竟会有几个线程?
  12. 办公计算机配件,办公电脑加装傲腾如丝般顺滑的办公体验
  13. cpu压测 windows_小白求问怎么用AIDA64进行CPU压力测试
  14. GPS模块开发详解(转)
  15. 最近k8s遇到的一些问题
  16. android studio 添加图片进入mipmap文件包
  17. 如何用java代码给Word文档添加水印?
  18. Laradock 下的 Laravel 项目如何使用 php artisan 命令
  19. 普陀区科技创新型小巨人企业奖励不超过100万元
  20. 【VM Ware】虚拟机安装XP系统时,出现546错误的解决办法

热门文章

  1. MySQL 4种text类型的最大长度
  2. 大剑无锋之你所知道的列式数据库有哪些?列式数据库的好处在哪?【面试推荐】
  3. 初探Apache Impala
  4. 终止进程的方法总结(使用)
  5. dart系列之:dart代码规范实践指南
  6. 小师妹学JVM之:JIT中的PrintAssembly
  7. 小师妹学JavaIO之:文件File和路径Path
  8. 人名和成绩一起排序_#excel中怎么让人名和他的成绩一起排序#excle排序 怎么弄同名次...
  9. SpringMVC之组合注解@GetMapping
  10. Linux网络编程 之 UDP编程(六)