本篇投稿来自 张智强 的投稿,分享了 Python 网络爬虫实战解析,希望大家喜欢。
他的博客是:http://blog.csdn.net/qq_33689414
代码地址:https://github.com/zhang3550545/xpath-spider/tree/master/jandan
前言
Python语言代码简短,功能精悍。如Python 之父所言 "人生苦短,我用 Python " 。所以 Python 语言写爬虫具有其他语言比不了的优势。Python 简直为爬虫而生。
在写爬虫程序之前,先说下爬虫程序的步骤,爬虫程序一般分为以下几步:
1. 明确爬虫需求
1.1 需求分析
2. 选择爬虫框架
2.1 框架简介
3. 编写爬虫程序
3.1 抓取网页数据
3.2 清洗网页数据(通过规则获取网页数据)
3.3 保存数据
正文
1. 明确爬虫需求
本文需要爬取的网站是:http://www.jandan.net/ooxx
需要爬取的内容是:爬取该网站的美女图片。
2. 需求分析
首先我们打开需要爬取的网站,选中一张美女图片,点击鼠标右键,选中检查,查看这张图片在 html 页面的位置。打开浏览器xpath-helper插件(没安装该插件可以通过浏览器应用安装),如下图所示:
通过使用xpath语法进行规则匹配,查找到我们想要的资源图片。同时我们也需要爬取下一页的图片数据,通过 xpath 语法找到下一页的 url ,加载下一页数据。所以我们需要采用递归的方式一页一页的爬取图片数据。
3. 爬虫框架的选择
本文采用Python3.6版本开发环境,网络请求框架使用:urllib , html 页面解析框架使用:lxml和xpath语法。最后将爬取的数据保存到本地文件。
4. urllib 框架简介
urllib是Python3.0的一个http网络请求框架,是系统的框架,功能比较强大。
urllib 类库包含四个模块:request模块,parse模块,error模块,robotparser模块。
我们一般常用的是 urllib.request 模块。下面介绍一下 request 模块的常用 api :
urlopen():请求url的方法,参数比较多,如下:
urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
*, cafile=None, capath=None, cadefault=False, context=None)
1.url:可以是一个string或者是一个Request对象。(重点)
2.data:默认是None。(重点)
如果传参需要传入dict字典类型。提供数据参数时,HTTP请求将是POST而不是GET
data应该使用application / x-www-form-urlencoded格式,需要urllib.parse.urlencode()进行编码。
3.timeout:超时时间
4.cafile:cafile应指向包含一系列CA证书的单个文件
5.capath:capath应指向散列证书文件的目录
6.cadefault:参数是否被忽略
7.context:如果指定了上下文,则它必须是描述各种SSL选项的ssl.SSLContext实例。
urlopen() 返回的一个上下文的管理对象,对于 http 返回的是一个http.client.HTTPResponse对象。
HTTPResponse对象
HTTPResponse对象,将响应的数据封装起来,常用的方法有:
response.geturl():返回检索资源的URL,通常用于确定是否遵循重定向
response.code():返回的是响应码
response.msg:返回的是响应信息
response.info():返回的是响应头信息
response.read():读取响应的数据,响应体
详细API可看下面官方文档:
urllib官网文档
https://docs.python.org/3.4/library/urllib.html
HTTPResponse官网文档
https://docs.python.org/3.4/library/http.client.html#http.client.HTTPResponse
5. lxml 简介
lxml类库是一个Html/XML的解析器,主要功能是如何解析和提取HTML/XML数据。
lxml 的安装
pip install lxml
lxml 的 api 介绍
lmxl借助etree模块,来处理 xml 和 html 的数据。如下所示:
1.将 html 页面数据转成 ElementTree 对象
tree = etree.HTML(text)
2.解析一个 html 文件,返回一个 ElementTree 对象
tree = etree.parse('xxxx.html')
3.通过 xpath 语法解析规则,解析 ElementTree 对象
参数 rule 是 xpath 解析 html 的规则(具体参考 xpath 语法文档)。
返回一个结果集(结果集有可能是 Element 的list集合,也有可能是字符串的list结合)
results = tree.xpath(rule)
4.将 Element/ElementTree 对象转成 html 的文本信息,返回一个文本信息
etree.tostring(element)
5.获取 Element 对象( html 标签)的文本信息
str = element.text
文档参考:
lxml 官方文档
http://lxml.de/index.html#documentation
xpath 语法文档
http://www.w3school.com.cn/xpath/xpath_syntax.asp
6. 编写爬虫程序
我们明确需求,选择好框架后,就开始编写爬虫程序了,我们将爬虫程序分为3步,抓取数据,清洗数据,保存数据。
第一步:封装
为了代码能很好的复用,我们把它封装成一个类JanDanSpider。定义3个方法,load_page(),parse_page(),load_image(), 如下:
classJanDanSpider(object):
def__init__(self):
pass
defload_page(self):
pass
defparse_page(self):
pass
defload_image(self):
pass
第二步:抓取网页数据
通过 urllib.request 模块,请求 url 链接,返回响应的内容。因为我们需要递归解析页面,以及加载图片,所有将请求的方法提取出来,封装成一个get_response()方法,具体如下:
importurllib.request
class JanDanSpider(object):
def__init__(self):
pass
defget_response(self , url):
# 修改http的headers的User-Agent头字段,如果不修改,默认是Python-urllib/3.6
# 如果使用默认的User-Agent,这样就直接暴露这是一个爬虫程序,就容易导致ip被封。
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36"
}
# 通过Request获取一个请求对象request
request = urllib.request.Request(url, headers = headres)
# 发送请求,返回一个响应对象response
response = urllib.request.urlopen(request)
# 将服务端返回的数据返回出去
return response.read()
def load_page(self , url):
# 1. 调用get_response方法,获取网页数据
response = self.get_response(url)
# 2. ... 下面继续
def parse_page(self):
pass
def save_image(self):
pass
第三步: 清洗网页数据
当我们获取网页返回的响应数据,接下来就是使用lxml和xpath规则解析网页的数据。
在 "http://www.jandan.net/ooxx" 网页中,有2种图片,一种是正常显示出来的 normal 图片,一种是大图,需要点击查看大图才能看到。除此之外,我们还需要解析出上一页的页面的 url 。
因为解析的方法都是一致的,只是 rule 的规则不同,返回的数据不同,所以我们将复用解析方法。传入 rule 参数。
import urllib.request
from lxml import etree
class JanDanSpider(object):
def__init__(self):
# 大图的xpath解析规则
self.rule_large = "//ol[@class='commentlist']/li//a[@class='view_img_link']/@href"
# 正常图的xpath解析规则
self.rule_normal = "//ol[@class='commentlist']/li//img/@src"
# 上一页的xpath解析规则
self.rule_pre_page = "//div[@class='comments']//a[@class='previous-comment-page']/@href"
def load_page(self , url):
# 获取服务端的响应数据
text = self.get_response(url)
# 通过大图的解析规则,处理大图的结果集
self.deal_images(self.parse_page(text, self.rule_large))
# 通过正常图的解析规则,处理正常图的结果集
self.deal_images(self.parse_page(text, self.rule_normal))
# 通过上一页的解析规则,处理上一页的结果集
self.deal_pre_page(self.parse_page(text, self.rule_pre_page))
def parse_page(self, text, rule):
"""
解析页面
:param text: 服务端返回的数据
:param rule: 解析规则
:return: 返回解析页面的结果
"""
# 通过etree库,将服务端返回的页面数据封装成ElementTree对象
tree = etree.HTML(text)
# 通过xpath规则(rule)解析ElementTree对象,返回数据列表
return tree.xpath(rule)
def deal_images(self, images):
"""
处理页面解析获得的图片
:param images: 解析页面返回的图片集合
:return:
"""
if images is not None:
# 遍历数据列表
for image in images:
if 'http:' not in image:
# 拼接图片的url
image = 'http:' + image
print(image)
# 下载图片
self.load_image(image)
def deal_pre_page(self, results):
"""
处理下一页
:param results: 解析页面结果
:return:
"""
if results is not None:
# 因为在页面有2处,解析有2个一样的地址#
if len(results) > 0:
# 取第一个
url = results[0]
if self.host in url:
if 'http:' not in url:
# 拼接字符串
url = 'http:' + url
# 加载下一个页面
self.load_page(url)
def load_image(self, image_url):
pass
第四步: 保存数据
最后获取的数据,是图片的url链接,我们需要将url链接下载对应的图片,并保存到本地。
classJanDanSpider(object):
defload_image(self, image_url):
"""
下载图片
:param image_url: 图片的url
:return:
"""
withopen(self.create_filename(image_url),'wb')asf:
f.write(self.get_response(image_url))
defcreate_filename(self, image_url):
"""
通过图片的url来确定存储路径
:param image_url: 图片的url
:return:
"""
results = image_url.split('/')
if'large'inimage_url:
filename ='image/large/'+ results[-1]
else:
filename ='image/normal/'+ results[-1]
returnfilename
最后我们调用爬虫程序,然后运行:
if__name__ =='main':
url ="http://jandan.net/ooxx"
spider = JanDanSpider()
spider.load_page(url)
运行输出的图片url,如图:
推荐阅读:
什么时候投递简历成功率最高?这是一个细致活!
程序员注意了,北京西二旗程序员因为这个被捕了
Chrome强大的15款插件,第2款简直是大学生的福音
2018年新版Java学习路线图(内含大纲+视频+工具+书籍+面试)
2018年最新Python学习路线图(内含大纲+视频+工具)
2018版Go语言+区块链学习路线图(含大纲+视频+工具+资料)
2018新版前端与移动开发学习路线图(视频+工具+书籍+资源)
好了,这里是传智播客——黑马程序员上海校区
想了解更多关于上海校区的学习资讯、开班信息、请速速联系你们的学姐,欢迎来撩!后期会持续更新!!!