其实在当今社会,网络上充斥着大量有用的数据,我们只需要耐心的观察,再加上一些技术手段,就可以获取到大量的有价值数据。这里的“技术手段”就是网络爬虫。今天就给大家分享一篇爬虫基础知识和入门教程:

什么是爬虫?

爬虫就是自动获取网页内容的程序,例如搜索引擎,Google,Baidu 等,每天都运行着庞大的爬虫系统,从全世界的网站中爬虫数据,供用户检索时使用。

爬虫流程

其实把网络爬虫抽象开来看,它无外乎包含如下几个步骤

模拟请求网页。模拟浏览器,打开目标网站。

获取数据。打开网站之后,就可以自动化的获取我们所需要的网站数据。

保存数据。拿到数据之后,需要持久化到本地文件或者数据库等存储设备中。

那么我们该如何使用 Python 来编写自己的爬虫程序呢,在这里我要重点介绍一个 Python 库:Requests。

Requests 使用

Requests 库是 Python 中发起 HTTP 请求的库,使用非常方便简单。

模拟发送 HTTP 请求

发送 GET 请求

当我们用浏览器打开豆瓣首页时,其实发送的最原始的请求就是 GET 请求

import requests

res = requests.get('http://www.douban.com')

print(res)

print(type(res))

>>>

可以看到,我们得到的是一个 Response 对象

如果我们要获取网站返回的数据,可以使用 text 或者 content 属性来获取

text:是以字符串的形式返回数据

content:是以二进制的方式返回数据

print(type(res.text))

print(res.text)

>>>

.....

发送 POST 请求

对于 POST 请求,一般就是提交一个表单

r = requests.post('http://www.xxxx.com', data={"key":"value"})

data 当中,就是需要传递的表单信息,是一个字典类型的数据。

header 增强

对于有些网站,会拒绝掉没有携带 header 的请求的,所以需要做一些 header 增强。比如:UA,Cookie,host 等等信息。

header = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36",

"Cookie":"your cookie"}

res = requests.get('http://www.xxx.com', headers=header)

解析 HTML

现在我们已经获取到了网页返回的数据,即 HTML 代码,下面就需要解析 HTML,来提取其中有效的信息。

BeautifulSoup

BeautifulSoup 是 Python 的一个库,最主要的功能是从网页解析数据。

frombs4 import BeautifulSoup # 导入 BeautifulSoup 的方法

# 可以传入一段字符串,或者传入一个文件句柄。一般都会先用 requests 库获取网页内容,然后使用 soup 解析。

soup = BeautifulSoup(html_doc,'html.parser') # 这里一定要指定解析器,可以使用默认的 html,也可以使用 lxml。

print(soup.prettify()) # 按照标准的缩进格式输出获取的 soup 内容。

BeautifulSoup 的一些简单用法

print(soup.title) # 获取文档的 title

print(soup.title.name) # 获取 title 的name属性

print(soup.title.string) # 获取 title 的内容

print(soup.p) # 获取文档中第一个 p 节点

print(soup.p['class']) # 获取第一个 p 节点的 class 内容

print(soup.find_all('a')) # 获取文档中所有的 a 节点,返回一个 list

print(soup.find_all('span', attrs={'style':"color:#ff0000"})) # 获取文档中所有的 span 且 style 符合规则的节点,返回一个 list

具体的用法和效果,我会在后面的实战中详细说明。

XPath 定位

XPath 是 XML 的路径语言,是通过元素和属性进行导航定位的。几种常用的表达式

表达式含义node选择 node 节点的所有子节点/从根节点选取//选取所有当前节点.当前节点..父节点@属性选取text()当前路径下的文本内容

一些简单的例子

xpath('node') # 选取 node 节点的所有子节点

xpath('/div') # 从根节点上选取 div 元素

xpath('//div') # 选取所有 div 元素

xpath('./div') # 选取当前节点下的 div 元素

xpath('//@id') # 选取所有 id 属性的节点

当然,XPath 非常强大,但是语法也相对复杂,不过我们可以通过 Chrome 的开发者工具来快速定位到元素的 xpath,如下图

得到的 xpath 为

//*[@id="anony-nav"]/div[1]/ul/li[1]/a

在实际的使用过程中,到底使用 BeautifulSoup 还是 XPath,完全取决于个人喜好,哪个用起来更加熟练方便,就使用哪个。

爬虫实战:爬取豆瓣海报

我们可以从豆瓣影人页,进入都影人对应的影人图片页面,比如以刘涛为例子,她的影人图片页面地址为

https://movie.douban.com/celebrity/1011562/photos/

下面我们就来分析下这个网页

目标网站页面分析

注意:网络上的网站页面构成总是会变化的,所以这里你需要学会分析的方法,以此类推到其他网站。正所谓授人以鱼不如授人以渔,就是这个原因。

Chrome 开发者工具

Chrome 开发者工具(按 F12 打开),是分析网页的绝佳利器,一定要好好使用。

我们在任意一张图片上右击鼠标,选择“检查”,可以看到同样打开了“开发者工具”,而且自动定位到了该图片所在的位置

可以清晰的看到,每张图片都是保存在 li 标签中的,图片的地址保存在 li 标签中的 img 中。

知道了这些规律后,我们就可以通过 BeautifulSoup 或者 XPath 来解析 HTML 页面,从而获取其中的图片地址。

代码编写

我们只需要短短的几行代码,就能完成图片 url 的提取

import requests

frombs4 import BeautifulSoup

url = 'https://movie.douban.com/celebrity/1011562/photos/'

res = requests.get(url).text

content = BeautifulSoup(res, "html.parser")

data = content.find_all('div', attrs={'class':'cover'})

picture_list = []

fordindata:

plist = d.find('img')['src']

picture_list.append(plist)

print(picture_list)

>>>

['https://img1.doubanio.com/view/photo/m/public/p2564834267.jpg','https://img1.doubanio.com/view/photo/m/public/p860687617.jpg','https://img1.doubanio.com/view/photo/m/public/p2174001857.jpg','https://img1.doubanio.com/view/photo/m/public/p1563789129.jpg','https://img3.doubanio.com/view/photo/m/public/p2363429946.jpg','https://img1.doubanio.com/view/photo/m/public/p2382591759.jpg','https://img3.doubanio.com/view/photo/m/public/p2363269182.jpg','https://img1.doubanio.com/view/photo/m/public/p1959495269.jpg','https://img3.doubanio.com/view/photo/m/public/p2356638830.jpg','https://img3.doubanio.com/view/photo/m/public/p1959495471.jpg','https://img3.doubanio.com/view/photo/m/public/p1834379290.jpg','https://img3.doubanio.com/view/photo/m/public/p2325385303.jpg','https://img3.doubanio.com/view/photo/m/public/p2361707270.jpg','https://img3.doubanio.com/view/photo/m/public/p2325385321.jpg','https://img3.doubanio.com/view/photo/m/public/p2196488184.jpg','https://img1.doubanio.com/view/photo/m/public/p2186019528.jpg','https://img1.doubanio.com/view/photo/m/public/p2363270277.jpg','https://img3.doubanio.com/view/photo/m/public/p2325240501.jpg','https://img1.doubanio.com/view/photo/m/public/p2258657168.jpg','https://img1.doubanio.com/view/photo/m/public/p2319710627.jpg','https://img3.doubanio.com/view/photo/m/public/p2319710591.jpg','https://img3.doubanio.com/view/photo/m/public/p2311434791.jpg','https://img1.doubanio.com/view/photo/m/public/p2363270708.jpg','https://img3.doubanio.com/view/photo/m/public/p2258657185.jpg','https://img3.doubanio.com/view/photo/m/public/p2166193915.jpg','https://img3.doubanio.com/view/photo/m/public/p2363265595.jpg','https://img3.doubanio.com/view/photo/m/public/p2312085755.jpg','https://img3.doubanio.com/view/photo/m/public/p2311434790.jpg','https://img3.doubanio.com/view/photo/m/public/p2276569205.jpg','https://img1.doubanio.com/view/photo/m/public/p2165332728.jpg']

可以看到,是非常干净的列表,里面存储了海报地址。

但是这里也只是一页海报的数据,我们观察页面发现它有好多分页,如何处理分页呢。

分页处理

我们点击第二页,看看浏览器 url 的变化

https://movie.douban.com/celebrity/1011562/photos/?type=C&start=30&sortby=like&size=a&subtype=a

发现浏览器 url 增加了几个参数

再点击第三页,继续观察 url

https://movie.douban.com/celebrity/1011562/photos/?type=C&start=60&sortby=like&size=a&subtype=a

通过观察可知,这里的参数,只有 start 是变化的,即为变量,其余参数都可以按照常理来处理

同时还可以知道,这个 start 参数应该是起到了类似于 page 的作用,start = 30 是第二页,start = 60 是第三页,依次类推,最后一页是 start = 420。

于是我们处理分页的代码也呼之欲出了

首先将上面处理 HTML 页面的代码封装成函数

def get_poster_url(res):

content = BeautifulSoup(res, "html.parser")

data = content.find_all('div', attrs={'class':'cover'})

picture_list = []

fordindata:

plist = d.find('img')['src']

picture_list.append(plist)

returnpicture_list

然后我们在另一个函数中处理分页和调用上面的函数

def fire():

page = 0

foriinrange(0, 450, 30):

print("开始爬取第 %s 页"% page)

url = 'https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)

res = requests.get(url).text

data = get_poster_url(res)

page += 1

此时,我们所有的海报数据都保存在了 data 变量中,现在就需要一个下载器来保存海报了

def download_picture(pic_l):

if notos.path.exists(r'picture'):

os.mkdir(r'picture')

foriinpic_l:

pic = requests.get(i)

p_name = i.split('/')[7]

withopen('picture\' + p_name, 'wb')asf:

f.write(pic.content)

再增加下载器到 fire 函数,此时为了不是请求过于频繁而影响豆瓣网的正常访问,设置 sleep time 为1秒

def fire():

page = 0

foriinrange(0, 450, 30):

print("开始爬取第 %s 页"% page)

url = 'https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)

res = requests.get(url).text

data = get_poster_url(res)

download_picture(data)

page += 1

time.sleep(1)

下面就执行 fire 函数,等待程序运行完成后,当前目录下会生成一个 picture 的文件夹,里面保存了我们下载的所有海报

核心代码讲解

下面再来看下完整的代码

import requests

frombs4 import BeautifulSoup

import time

import osdef fire():

page = 0

foriinrange(0, 450, 30):

print("开始爬取第 %s 页"% page)

url = 'https://movie.douban.com/celebrity/1011562/photos/?type=C&start={}&sortby=like&size=a&subtype=a'.format(i)

res = requests.get(url).text

data = get_poster_url(res)

download_picture(data)

page += 1

time.sleep(1)def get_poster_url(res):

content = BeautifulSoup(res, "html.parser")

data = content.find_all('div', attrs={'class':'cover'})

picture_list = []

fordindata:

plist = d.find('img')['src']

picture_list.append(plist)

returnpicture_listdef download_picture(pic_l):

if notos.path.exists(r'picture'):

os.mkdir(r'picture')

foriinpic_l:

pic = requests.get(i)

p_name = i.split('/')[7]

withopen('picture\' + p_name, 'wb')asf:

f.write(pic.content)if __name__ == '__main__':

fire()

fire 函数

这是一个主执行函数,使用 range 函数来处理分页。

range 函数可以快速的创建整数列表,在 for 循环时及其好用。函数中的0代表从0开始计数,450代表一直迭代到450,不包含450,30代表步长,即每次递增的数字间隔。range(0, 450, 30),依次会输出:0,30,60,90 …

format 函数,是一种字符串格式化方式

time.sleep(1) 即为暂停1秒钟

get_poster_url 函数

这个就是解析 HTML 的函数,使用的是 BeautifulSoup

通过 find_all 方法查找所有 class 为 “cover” 的 div 元素,返回的是一个列表

使用 for 循环,循环上一步拿到的列表,取出 src 的内容,append 到列表中

append 是列表的一个方法,可以在列表后面追加元素

download_picture 函数

简易图片下载器

首先判断当前目录下是否存在 picture 文件夹,os.path.exists

os 库是非常常用用来操作系统相关的命令库,os.mkdir 就是创建文件夹

split 用于切割字符串,取出角标为7的元素,作为存储图片的名称

with 方法用来快速打开文件,打开的进程可以自行关闭文件句柄,而不再需要手动执行 f.close() 关闭文件

总结

本节讲解了爬虫的基本流程以及需要用到的 Python 库和方法,并通过一个实际的例子完成了从分析网页,到数据存储的全过程。其实爬虫,无外乎模拟请求,解析数据,保存数据。

当然有的时候,网站还会设置各种反爬机制,比如 cookie 校验,请求频度检查,非浏览器访问限制,JS 混淆等等,这个时候就需要用到反反爬技术了,比如抓取 cookie 放到 headers 中,使用代理 IP 访问,使用 Selenium 模拟浏览器等待方式。

由于本课程不是专门的爬虫课,这些技能就留待你自己去探索挖掘啦。

【编辑推荐】

【责任编辑:未丽燕 TEL:(010)68476606】

点赞 0

python爬虫教程下载-Python爬虫入门教程!手把手教会你爬取网页数据相关推荐

  1. python爬取网页汉字_程序小技巧:Python3借助requests类库3行代码爬取网页数据!快来...

    爬取网页数据是python很长干的一件事情,不过做起来基本上都是很冗长的一段代码,看起来复杂,不宜理解.今天给大家分享一个小诀窍,利用python3中的requests类库进行爬取网页数据. 我们先看 ...

  2. python爬虫教程:实例讲解Python爬取网页数据

    这篇文章给大家通过实例讲解了Python爬取网页数据的步骤以及操作过程,有兴趣的朋友跟着学习下吧. 一.利用webbrowser.open()打开一个网站: >>> import w ...

  3. 如何用python爬取网页数据,python爬取网页详细教程

    大家好,本文将围绕python怎么爬取网站所有网页展开说明,如何用python爬取网页数据是一个很多人都想弄明白的事情,想搞清楚python如何爬取网页数据需要先了解以下几个事情. 1.如何用Pyth ...

  4. 编程python爬取网页数据教程_实例讲解Python爬取网页数据

    一.利用webbrowser.open()打开一个网站: >>> import webbrowser >>> webbrowser.open('http://i.f ...

  5. python爬虫爬网站数据登录_使用webdriver+urllib爬取网页数据(模拟登陆,过验证码)...

    urilib是python的标准库,当我们使用Python爬取网页数据时,往往用的是urllib模块,通过调用urllib模块的urlopen(url)方法返回网页对象,并使用read()方法获得ur ...

  6. Python爬虫爬取网页数据并存储(一)

    Python爬虫爬取网页数据并存储(一) 环境搭建 爬虫基本原理 urllib库使用 requests库使用 正则表达式 一个示例 环境搭建 1.需要事先安装anaconda(或Python3.7)和 ...

  7. Python小姿势 - Python爬取网页数据

    Python爬取网页数据 爬取网页数据是一个比较常见的Python应用场景,有很多第三方库可以帮助我们完成这个任务.这里我们介绍一下urllib库中的一个常用方法:urllib.request.url ...

  8. java爬取网页数据_利用Python做数据分析—对前程无忧数据类岗位进行分析

    引言 随着时代的发展,我国在各行各业都需要大量的人才引进,处于近几年最热门的行业也称"最火行业":大数据.数据分析.数据挖掘.机器学习.人工智能,这五门行业各有不同又互有穿插.近几 ...

  9. python爬取网页公开数据_如何用Python爬取网页数据

    使用Python爬取网页数据的方法: 一.利用webbrowser.open()打开一个网站:>>> import webbrowser >>> webbrowse ...

最新文章

  1. Day 17: 使用 JBoss Forge 和 OpenShift 构建部署 JAVA EE 6 应用
  2. Explaining the Genesis Block in Ethereum
  3. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析
  4. GoAhead 2.5 Web Server 网页ROM化的改进
  5. Linux 查看CPU信息、机器型号等硬件信息
  6. 前瞻科技,引领未来!Microsoft Connect(); 2018即将重磅来袭!
  7. PHP实现对MongoDB的基础操作
  8. db2如何锁定一张表_DB2数据库为单个会话锁定的技巧
  9. qt添加qwt帮助文件_qt creator中使用qwt插件
  10. c++ 结构体中不同类型的初始值_不同类型结构的厂房效果图大盘点
  11. 搜索引擎Elasticsearch,这篇文章给讲透了(建议收藏)
  12. 计算机网络为什么要分层?
  13. Word导航窗格显示自定义标题样式的方法
  14. 微信代金券--免充值代金券创建、激活、发放,查看详情
  15. html5 css 插入视频,HTML+CSS入门 HTML网页中插入视频各种方法
  16. python入门基础要点,入门决定没问题(初学者专属)
  17. 我的游戏开发收藏夹 (不定期更新)
  18. [可解释机器学习]Task07:LIME、shap代码实战
  19. 【C++】Web服务器项目所用到的函数详解
  20. 知网文献免费下载方法

热门文章

  1. java 字符整数_Java整数是否等于字符?
  2. mysql foreign key 设置_mysql foreign key(外键) 说明与实例
  3. vim-commentary 插件用法
  4. AndroidStudio3.4.2 gradle5.1.1 apt注解解释器不执行
  5. 暗网 tor溯源困难根因——用户的请求会在分布全球的主机随机跳转三次,最终才到达服务器,这就造成了溯源的极其困难...
  6. 通过DNS通道传输的交互式PowerShell脚本
  7. 一致性哈希算法——算法解决的核心问题是当slot数发生变化时,能够尽量少的移动数据...
  8. peewee flask pwiz 中使用模型 过一段时间报错 peewee.InterfaceError: (0, '') 的解决方式
  9. PHP函数处理方法总结
  10. [LeetCode] Search Insert Position 搜索插入位置