学习爬虫之前,我们首先得理解什么是爬虫。来自于百度百科的阐明:
网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更常常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。
普通来讲,如果你须要互联网上的信息,如商品价格,图片视频资源等,但你又不想或者不能自己一个一个自己去打开网页网络,这时候你便写了一个程序,让程序按照你指定好的规则去互联网上网络信息,这便是爬虫,我们熟知的百度,谷歌等搜索引擎背后实在也是一个巨大的爬虫。
爬虫合法吗?
可能很多小伙伴都会有这个疑问,首先爬虫是一门技能,技能该当是中立的,合不合法实在取决于你利用目的,是由爬虫背后的人来决定的,而不是爬虫来决定的。
一样平常来说只要不影响人家网站的正常运转,也不是出于商业目的,人家一样平常也就只会封下的IP,账号之类的,不至于法律风险。
实在大部分网站都会有一个robots协议,在网站的根目录下会有个robots.txt的文件,里面写明了网站里面哪些内容可以抓取,哪些不许可。
以淘宝为例——https://www.taobao.com/robots.txt
淘宝robots协议中针对百度与谷歌的爬取限定
当然robots协议本身也只是一个业内的约定,是不具有法律意义的,以是遵不遵守呢也只能取决于用户本身的底线了。
Why Python很多人提到爬虫就会想到Python,实在除了Python,其他的措辞诸如C,PHP,Java等等都可以写爬虫,而且一样平常来说这些措辞的实行效率还要比Python要高,但为什么目前来说,Python逐渐成为了写很多人写爬虫的第一选择,我大略总结了以下几点:
开拓效率高,代码简洁,一行代码就可完成要求,100行可以完成一个繁芜的爬虫任务;爬虫对付代码实行效率哀求不高,网站IO才是最影响爬虫效率的。如一个网页要求可能须要100ms,数据处理10ms还是1ms影响不大;非常多精良的第三方库,如requests,beautifulsoup,selenium等等;本文后续内容也将会以Python作为根本来进行讲解。环境准备Python安装,这部分可以参考我之前的文章Python环境配置&Pycharm安装,辞官网下载对应的安装包,一起Next安装就行了;pip安装,pip是Python的包管理器,现在的Python安装包一样平常都会自带pip,不须要自己再去额外安装了;requests,beautifulsoup库的安装,通过以下语句来完成安装:pip install requestspip install beautifulsoup4谷歌浏览器(chrome);第三方库先容requests官方中文文档:https://2.python-requests.org/zh_CN/latest/;
requests该当是用Python写爬虫用到最多的库了,同时requests也是目前Github上star✨最多的Python开源项目。requests在爬虫中一样平常用于来处理网络要求;
接下来会用通过大略的示例来展示requests的基本用法:
首先我们须要导入requests模块;
import requests
接着我们考试测验向baidu发起要求;
r = requests.get(39;https://www.baidu.com/')1
我们现在得到来命名为r的response工具,从这个工具中我们便可以获取到很多信息,如:状态码,200即为要求成功页面Html5代码
# 返回要求状态码,200即为要求成功print(r.status_code)# 返回页面代码print(r.text)# 对付特定类型要求,如Ajax要求返回的json数据print(r.json())
当然对付大部分网站都会须要你表明你的身份,我们一样平常正常访问网站都会附带一个要求头(headers)信息,里面包含了你的浏览器,编码等内容,网站会通过这部分信息来判断你的身份,以是我们一样平常写爬虫也加上一个headers;
# 添加headersheaders = {'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'}r = requests.get('https://www.baidu.com/', headers=headers)
针对post要求,也是一样大略;
# 添加headersheaders = {'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'}# post要求data = {'users': 'abc', 'password': '123'}r = requests.post('https://www.weibo.com', data=data, headers=headers)
很多时候即是须要登录的站点我们可能须要保持一个会话,不然每次要求都先登录一遍效率太低,在requests里面一样很大略;
# 保持会话# 新建一个session工具sess = requests.session()# 先完成登录sess.post('maybe a login url', data=data, headers=headers)# 然后再在这个会话下去访问其他的网址sess.get('other urls')
beautifulsoup当我们通过requests获取到全体页面的html5代码之后,我们还得进一步处理,由于我们须要的每每只是全体页面上的一小部分数据,以是我们须要对页面代码html5解析然后筛选提取出我们想要的数据,这时候beautifulsoup便派上用场了。beautifulsoup之后通过标签+属性的办法来进行定位;
比如说我们想要爬取百度的logo,我们查看页面的html5代码,我们可以创造logo图片是在一个div的标签下,然后class=index-logo-srcnew这个属性下。
浏览器F12打开掌握台即可看到页面代码
以是我们如果须要定位logo图片的话便可以通过div和class=index-logo-srcnew来进行定位。下面也会供应一些大略的示例来解释beautifulsoup的基本用法:
导入beautifulsou模块;
from bs4 import BeautifulSoup
对页面代码进行解析,这边选用对html代码是官方示例中利用的爱丽丝页面代码;
html = """<html><head><title>The Dormouse's story</title></head><body><p class="title" name="dromouse"><b>The Dormouse's story</b></p><p class="story">Once upon a time there were three little sisters; and their names were<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;and they lived at the bottom of a well.</p><p class="story">...</p>"""# 选用lxml解析器来解析soup = BeautifulSoup(html, 'lxml')
我们现在得到一个命名为soup的Beautifulsoup工具,从这个工具中我们便能定位出我们想要的信息,如:
# 获取标题print(soup.title)# 获取文本print(soup.title.text)# 通过标签定位print(soup.find_all('a'))# 通过属性定位print(soup.find_all(attrs={'id': 'link1'}))# 标签 + 属性定位print(soup.find_all('a', id='link1'))
打印结果如下:
<title>The Dormouse's story</title>The Dormouse's story[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>][<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>][<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
案例分享获取17173新游频道下贱戏名定位我们所须要的信息,记住html里面的位置。这边可以分享一个小技巧,以前我刚开始写爬虫的时候,探求代码里面的信息都是先去把全体页面给down下来,然后再在里面Ctrl+F查找,实在大部分浏览器都供应了很大略的方法来定位页面代码位置的,这边会以Chrome浏览器为例。
为了方便理解录制了一个gif,详细步骤如下:
F12打开掌握台,选择element标签查看页面代码;点击掌握台左上角箭头,然后点击页面上我们须要的信息,我们可以看到掌握台中页面代码直接跳转到对应的位置;页面代码中一贯向上选择标签直至席卷我们须要的所有信息;记住此时的标签以及属性等信息,这将会用于后面解析筛选数据。接下来便可以开始敲代码了,完全代码如下,对付每个步骤均有详细的注释:
from bs4 import BeautifulSoupimport requests# 页面url地址url = 'http://newgame.17173.com/game-list-0-0-0-0-0-0-0-0-0-0-1-2.html'# 发送要求,r为页面相应r = requests.get(url)# r.text获取页面代码# 利用lxml解析页面代码soup = BeautifulSoup(r.text, 'lxml')# 两次定位,先找到全体信息区域info_list = soup.find_all(attrs={'class': 'ptlist ptlist-pc'})# 在此区域内获取游戏名,find_all返回的是listtit_list = info_list[0].find_all(attrs={'class': 'tit'})# 遍历获取游戏名# .text可获取文本内容,更换掉文章中的换行符for title in tit_list: print(title.text.replace('\n', ''))
获取拉勾网职位信息目前很多网站上的信息都是通过Ajax动态加载的;
比如当你翻看某电商网站的评论,当你点击下一页的时候,网址并没发生变革,但上面的评论都变了,这实在便是通过Ajax动态加载出来的;
这里的下一页序序按钮并不是指向其余一个页面,而是会在后台发送一个要求,做事器吸收到这个要求之后会在当前页面上渲染出来;
实在我自己是比较偏爱爬这种类型的数据的,由于统计Ajax要求返回来的数据都是非常规整的json数据,不须要我们去写繁芜的表达式去解析了;
接下来我们将会通过一个拉勾网职位信息的爬虫来解释这类网站的爬取流程:
F12打开掌握台,然后搜索‘数据剖析’,把稳一定是先打开掌握台,然后再去搜索,不然要求信息是没有记录下来的。然后我们去Network标签下的XHR下查找我们须要的要求(动态加载的数要求都是在XHR下);然后我们切换到headers标签下,我们可以看到要求的地址和所需到参数等信息;实验几次之后我们便能创造这三个参数的含义分别是:first:是否首页pn:页码kd:搜索关键词正常来说我们直接向这个网址传first, pn,kd三个参数就好了,不过考试测验了几次之后创造拉勾有如下比较故意思的限定:headers里面referer参数是必须的,referer是向做事器表示你是从哪个页面跳转过来的;必须得先访问这个referer的网址,然后再去要求职位信息的API。代码如下,也很大略,不过三十几行:
import requestsclass Config: kd = '数据剖析' referer = 'https://www.lagou.com/jobs/list_%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90?labelWords=&fromSearch=true&suginput=' headers = { 'Accept': 'application/json, text/javascript, /; q=0.01', 'Referer': referer, 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/' '537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'}class Spider: def __init__(self, kd=Config.kd): self.kd = kd self.url = Config.referer self.api = 'https://www.lagou.com/jobs/positionAjax.json' # 必须先要求referer网址 self.sess = requests.session() self.sess.get(self.url, headers=Config.headers) def get_position(self, pn): data = {'first': 'true', 'pn': str(pn), 'kd': self.kd } # 向API发起POST要求 r = self.sess.post(self.api, headers=Config.headers, data=data) # 直接.json()解析数据 return r.json()['content']['positionResult']['result'] def engine(self, total_pn): for pn in range(1, total_pn + 1): results = self.get_position(pn) for pos in results: print(pos['positionName'], pos['companyShortName'], pos['workYear'], pos['salary'])if __name__ == '__main__': lagou = Spider() lagou.engine(2)
附上实行结果:
数据剖析-客服中央(J10558) 哈啰出行 3-5年 9k-15k大数据剖析师 建信金科 3-5年 16k-30k......数据剖析师-【快影】 快手 3-5年 15k-30k数据剖析师(业务剖析)-【商业化】 快手 3-5年 20k-40k数据剖析师 思创客 1-3年 6k-12k