Python之简单的网页爬虫开发
Python之简单的网页爬虫开发
文章目录
- Python之简单的网页爬虫开发
- 下面简单介绍一下request:
- 简单介绍一下什么是第三方库:
- 结合requests与正则表达式
- 多线程爬虫
- 多进程库(multiprocessing)
- 开发多线程爬虫
- 爬虫的常见搜索算法
- 深度优先搜索
- 广度优先搜索
- 爬虫搜索算法的选择
第一步:
我们要获取爬取数据的url地址
我们要用到request请求.
下面简单介绍一下request:
requests是Python的一个第三方HTTP(Hypertext Transfer Protocol,超文本传输协议)库,它比Python自带的网络库urllib更加简单、方便和人性化。使用requests可以让Python实现访问网页并获取源代码的功能。
使用requests获取网页的源代码,最简单的情况下只需要两行代码:
#使用requests获取源代码
import requests
source = requests.get('https://www.baidu.com').content.deocde()
上面的request就是Python的第三方库,我们在用爬虫的时候要用到的就是Python的第三方库
简单介绍一下什么是第三方库:
在Python开发的过程中,常常需要将一些功能比较通用的代码抽离出来作为一个单独的模块,从而被多个工程调用。这种公共的模块称为Python的库(Library,Lib)。
Python在发布时会自带一些由官方开发的常用的库,例如正则表达式“re”、时间“time”等。这些库称为“官方库”。而由非官方发布的库,则称为“第三方库”。
下面就是request的安装:
使用pip安装requests,代码如下:
pip install requests
运行结果如图4-1所示。
pip在线安装时可能会受到防火墙的干扰,因此也可以使用源代码安装。打开网页https://github.com/kennethreitz/requests,单击“Clone or download”按钮,再单击“Download ZIP”按钮下载源代码,如图4-2所示
解压源代码,找到setup.py,并打开CMD窗口或者终端,在放置这个setup.py文件的文件夹中执行以下代码:
python3 setup.py install
安装完成以后打开CMD或者终端,进入Python交互环境,输入以下代码:
import requests
如果不报错,则表示requests已经成功安装,如图4-3所示。
下面我们就来使用request爬取网页:
使用浏览器来访问网页,看起来只需要输入网址就可以。但其实网页有很多种打开方式,最常见的是GET方式和POST方式。
在浏览器里面可以直接通过输入网址访问的页面,就是使用了GET方式。
还有一些页面,只能通过从另一个页面单击某个链接或者某个按钮以后跳过来,不能直接通过在浏览器输入网址访问,这种网页就是使用了POST方式。
GET方式
对于使用GET方式的网页,在Python里面可以使用requests的get()方法获取网页的源代码:
import requests
html=requests.get("网址")
html_bytes=html.content
html_str=html_bytes.decode()
或者一步:
page=htm.content.decode()
例:使用GET方式获取网页源代码。
通过http://exercise.kingname.info/exercise_requests_get.html可以测试使用requests的get()方法获取网页,网页如图4-4所示
使用requests获取这个页面的源代码,其结果如图4-5所示
POST方式
网页的访问方式除了GET方式以外,还有POST方式。有一些网页,使用GET和POST方式访问同样的网址,得到的结果是不一样的。还有另外一些网页,只能使用POST方式访问,如果使用GET方式访问,网站会直接返回错误信息。
例:使用POST方式获取网站源代码。
以http://exercise.kingname.info/exercise_requests_post为例,如果直接使用浏览器访问,得到的页面如图4-6所示
此时就需要使用requests的post()方法来获取源代码。
post()方法的格式如下:
import requests
data={'key1':'value1',
'key2':'value2'}
html_formdat=requests.post('网址',data=data).content.decode()
#用formdata提交数据
中,data这个字典的内容和项数需要根据实际情况修改,Key和Value在不同的网站是不一样的。而做爬虫,构造这个字典是任务之一。
还有一些网址,提交的内容需要是JSON格式的,因此post()方法的参数需要进行一些修改:
html_json = requests.post('网址', json=data).content.decode() #使用JSON提交数据
这样写代码,requests可以自动将字典转换为JSON字符串。
对练习网址使用两种提交方式,其结果如图4-7、图4-8所示
结合requests与正则表达式
以GET方式为例,通过requests获得了网页的源代码,就可以对源代码字符串使用正则表达式来提取文本信息。
GET方式练习页面的源代码如图4-9所示
例:使用requests与正则表达式获取GET练习页面的内容。
现在需要把标题和两段中文提取下来,可以通过正则表达式来实现。
① 提取标题。
title = re.search(‘title>(.*?)<’, html, re.S).group(1)
② 提取正文,并将两段正文使用换行符拼接起来。
content_list = re.findall(‘p>(.*?)<’, html, re.S)
content_str = ‘\n’.join(content_list)
完整的代码和运行效果如图4-10所示
多线程爬虫
在掌握了requests与正则表达式以后,就可以开始实战爬取一些简单的网址了。
但是,此时的爬虫只有一个进程、一个线程,因此称为单线程爬虫。单线程爬虫每次只访问一个页面,不能充分利用计算机的网络带宽。一个页面最多也就几百KB,所以爬虫在爬取一个页面的时候,多出来的网速和从发起请求到得到源代码中间的时间都被浪费了。
如果可以让爬虫同时访问10个页面,就相当于爬取速度提高了10倍。为了达到这个目的,就需要使用多线程技术了。
微观上的单线程,在宏观上就像同时在做几件事。这种机制在I/O(Input/Output,输入/输出)密集型的操作上影响不大,但是在CPU计算密集型的操作上面,由于只能使用CPU的一个核,就会对性能产生非常大的影响。所以涉及计算密集型的程序,就需要使用多进程,Python的多进程不受GIL的影响。
爬虫属于I/O密集型的程序,所以使用多线程可以大大提高爬取效率。
多进程库(multiprocessing)
multiprocessing本身是Python的多进程库,用来处理与多进程相关的操作。但是由于进程与进程之间不能直接共享内存和堆栈资源,而且启动新的进程开销也比线程大得多,因此使用多线程来爬取比使用多进程有更多的优势。multiprocessing下面有一个dummy模块,它可以让Python的线程使用multiprocessing的各种方法。
dummy下面有一个Pool类,它用来实现线程池。这个线程池有一个map()方法,可以让线程池里面的所有线程都“同时”执行一个函数。
例:计算0~9的每个数的平方。
在学习了for循环之后,代码可能会写成这样:
for i in range(10):print(i ** i)
这种写法当然可以得到结果,但是代码是一个数一个数地计算,效率并不高。而如果使用多线程的技术,让代码同时计算很多个数的平方,就需要使用multiprocessing.dummy来实现:
from multiprocessing.dummy import Pooldef calc_power2(num):#定义一个函数用来计算平方return num * numpool = Pool(3)#初始化三个线程
origin_num = [x for x in range(10)]
result = pool.map(calc_power2, origin_num)
print(f'计算0-9的平方分别为:{result}')
在上面的代码中,先定义了一个函数用来计算平方,然后初始化了一个有3个线程的线程池。这3个线程负责计算10个数字的平方,谁先计算完手上的这个数,谁就先取下一个数继续计算,直到把所有的数字都计算完成为止。
在这个例子中,线程池的map()方法接收两个参数,第1个参数是函数名,第2个参数是一个列表。注意:第1个参数仅仅是函数的名字,是不能带括号的。第2个参数是一个可迭代的对象,这个可迭代对象里面的每一个元素都会被函数clac_power2()接收来作为参数。除了列表以外,元组、集合或者字典都可以作为map()的第2个参数。
代码的运行结果如图4-11所示
开发多线程爬虫
由于爬虫是I/O密集型的操作,特别是在请求网页源代码的时候,如果使用单线程来开发,会浪费大量的时间来等待网页返回,所以把多线程技术应用到爬虫中,可以大大提高爬虫的运行效率。
下面通过两段代码来对比单线程爬虫和多线程爬虫爬取百度首页的性能差异
使用单线程循环访问百度首页100次,计算总时间,代码如下:
def query(url):requests.get(url)start = time.time()
for i in range(100):query('https://baidu.com')
end = time.time()
print(f'单线程循环访问100次百度首页,耗时:{end - start}')
使用5个线程访问100次百度首页,计算总时间,代码如下:
start = time.time()
url_list = []
for i in range(100):url_list.append('https://baidu.com')
pool = Pool(5)
pool.map(query, url_list)
end = time.time()
print(f'5线程访问100次百度首页,耗时:{end - start}')
如图4-12:
从运行结果可以看到,一个线程用时约16.2s,5个线程用时约3.5s,时间是单线程的五分之一左右。从时间上也可以看到5个线程“同时运行”的效果。
但并不是说线程池设置得越大越好。从上面的结果也可以看到,5个线程运行的时间其实比一个线程运行时间的五分之一要多一点。这多出来的一点其实就是线程切换的时间。这也从侧面反映了Python的多线程在微观上还是串行的。
因此,如果线程池设置得过大,线程切换导致的开销可能会抵消多线程带来的性能提升。
线程池的大小需要根据实际情况来确定,并没有确切的数据。
读者可以在具体的应用场景下设置不同的大小进行测试对比,找到一个最合适的数据。
爬虫的常见搜索算法
在角色扮演类游戏中,玩家需要在游戏里领取任务。有的人喜欢一次只领取一个任务,把这个任务做完,再去领下一个任务,这就叫作深度优先搜索。
还有一些人喜欢先把能够领取的所有任务一次性领取完,然后去慢慢完成,最后再一次性把任务奖励都领取了,这就叫作广度优先搜索。
深度优先搜索
假设图4-13是某在线教育网站的课程分类,需要爬取上面的课程信息。从首页开始,课程有几个大的分类,比如根据语言分为Python、Node.js和Golang。
每个大分类下面又有很多的课程,比如Python下面有爬虫、Django和机器学习。每个课程又分为很多的课时。
在深度优先搜索的情况下,爬取路线如图所示(序号从小到大)。
如图4-13:
如图4-14:
路线为“首页→Python→爬虫→课时1→课时2→……→课时N→Django→机器学习→Node.js→基础知识→Express→Golang→基础知识→并行计算”。也就是说,把爬虫的所有课时都爬取完成,再爬取Django的所有课程,接着爬取机器学习的所有课程,之后再去爬取Node.js的所有信息……
广度优先搜索
在广度优先搜索的情况下,爬取路线如图4-15所示(序号从小到大)。
路线为“首页→Python→Node.js→Golang→爬虫→Django→机器学习→基础知识→Express→基础知识→并行计算→课时1→课时2→……→课时N”。也就是说,首先爬取每个大分类的信息,然后从第1个大分类中爬取所有的课程信息,爬完了第1个大分类,再爬第2个大分类,直到所有大分类下面的课程信息都搞定了,再爬第一个课程的所有课时信息……
爬虫搜索算法的选择
在爬虫开发的过程中,应该选择深度优先还是广度优先呢?这就需要根据被爬取的数据来进行选择了。
例如要爬取某网站全国所有的餐馆信息和每个餐馆的订单信息。假设使用深度优先算法,那么先从某个链接爬到了餐馆A,再立刻去爬餐馆A的订单信息。由于全国有十几万家餐馆,全部爬完可能需要12小时。这样导致的问题就是,餐馆A的订单量可能是早上8点爬到的,而餐馆B是晚上8点爬到的。它们的订单量差了12小时。
而对于热门餐馆来说,12小时就有可能带来几百万的收入差距。这样在做数据分析时,12小时的时间差就会导致难以对比A和B两个餐馆的销售业绩。
相对于订单量来说,餐馆的数量变化要小得多。所以如果采用广度优先搜索,先在半夜0点到第二天中午12点把所有的餐馆都爬取一遍,第二天下午14点到20点再集中爬取每个餐馆的订单量。这样做,只用了6个小时就完成了订单爬取任务,缩小了由时间差异致的订单量差异。同时由于店铺隔几天抓一次影响也不大,所以请求量也减小了,使爬虫更难被网站发现。
所以我们在用爬虫的时候要认真考虑我们到底该选择哪种爬虫的搜索算法的选择
Python之简单的网页爬虫开发相关推荐
- 3.简单的网页爬虫开发
目录 一.爬虫开发中的法律与道德问题 1.数据采集的法律问题 (1)妨害个人信息安全 (2)涉及国家安全信息 (3)妨害网站正常运行 (4)侵害他人利益 (5)内幕交易 2.道德协议 (1)Robot ...
- 【Python 爬虫】简单的网页爬虫
这边有一个用来测试的网站点击跳转 简单的网页爬虫 requests的使用 使用requests获取网页的源代码 requests与正则结合 多线爬虫 多进程库 开发多线程爬虫 爬虫算法的开发 深度优先 ...
- 利用 Python 实现简单的主题爬虫
利用 Python 实现简单的主题爬虫 利用 Python 实现简单的主题爬虫,主要是通过对指定的 主题 和 网站 进行深度爬取,获取对应网页的标题和 url ,仅供学习参考. 爬取结果: 实验源 ...
- python制作查询网页_Python制作简单的网页爬虫
1.准备工作: 工欲善其事必先利其器,因此我们有必要在进行Coding前先配置一个适合我们自己的开发环境,我搭建的开发环境是: 操作系统:Ubuntu 14.04 LTS Python版本:2.7.6 ...
- python制作简单网页_Python制作简单的网页爬虫
1.准备工作: 工欲善其事必先利其器,因此我们有必要在进行Coding前先配置一个适合我们自己的开发环境,我搭建的开发环境是: 操作系统:Ubuntu 14.04 LTS Python版本:2.7.6 ...
- 实战|Python轻松实现动态网页爬虫(附详细源码)
用浅显易懂的语言分享爬虫.数据分析及可视化等干货,希望人人都能学到新知识. 项目背景 事情是这样的,前几天我公众号写了篇爬虫入门的实战文章,叫做<实战|手把手教你用Python爬虫(附详细源码) ...
- beautifulsoup解析动态页面div未展开_实战|Python轻松实现动态网页爬虫(附详细源码)...
用浅显易懂的语言分享爬虫.数据分析及可视化等干货,希望人人都能学到新知识.项目背景事情是这样的,前几天我公众号写了篇爬虫入门的实战文章,叫做<实战|手把手教你用Python爬虫(附详细源码)&g ...
- Python轻松实现动态网页爬虫(附详细源码)!
AJAX动态加载网页 一 什么是动态网页 J哥一向注重理论与实践相结合,知其然也要知其所以然,才能以不变应万变. 所谓的动态网页,是指跟静态网页相对的一种网页编程技术.静态网页,随着html代码的生成 ...
- python简单网络爬虫_【Python】简单的网络爬虫
完整代码 # encoding:UTF-8 # from bs4 import BeautifulSoup import urlparse import urllib2 import re impor ...
最新文章
- 使用微软提供的Office Online实现Office文档的在线查看,编辑等功能
- Robot framework+python安装使用图解版
- 基于 Apache Flink + Hologres 的实时推荐系统架构解析
- CodeForces - 897E Willem, Chtholly and Seniorious(珂朵莉树)
- KNN K近邻算法学习
- 【elasticsearch】 基于_version进行乐观锁并发控制
- Django实例-静态访问
- 【学习笔记】信息系统项目管理-项目採购管理-合同分类
- python关于pyaudio无法import的一系列问题
- 阿米洛键盘失灵_机械键盘按键失灵维修,这里有个案例给你一些思路。
- 【例题】利用伴随矩阵求逆矩阵
- win7系统安装卡在启动服务器,安装win7卡在启动界面不动进不了BIOS的解决方法 - 系统家园...
- uni-app 文件选择、文件管理器(ios11)
- SQLServer查询某天数据语法
- RB-tree性质理解
- 【mq】从零开始实现 mq-09-消费者拉取消息 pull message
- 复旦大学计算机专硕学制几年,复旦大学硕士研究生学制是几年
- 编程题目分类(剪辑)
- 无领导小组讨论面试真题解析(八)—— 是什么影响了利润
- Oracle SQL优化准则
热门文章
- 区块链凉了吗?真没有,应用模式已经有谱了
- 屏幕录制为什么没声音?检查这2项,轻松解决
- 魅族手机网络邻居开启后无法连接电脑,电脑无法通过IP地址访问手机文件夹
- (3)在linux ubuntu16版本当中安装anaconda
- elementui导出数据为xlsx、excel表格
- 2019澳大利亚网球公开赛即将开赛
- 邯郸轻化工学校计算机,邯郸轻化工学校中等职业学校计算机应用专业教学标准试行一.DOC...
- python 决策树回归参数_使用 Python 和 scikit-learn 学习回归算法
- Linux 批量修改文件后缀
- Android系统SD卡管理