Python爬虫之静态页面爬取 |
您所在的位置:网站首页 › 静态网页的含义 › Python爬虫之静态页面爬取 |
Python爬虫之静态页面爬取
前言
Python语言代码简短,功能精悍。如Python之父所言 “人生苦短,我用Python” 。所以Python语言写爬虫具有其他语言比不了的优势。Python简直为爬虫而生。 在写爬虫程序之前,先说下爬虫程序的步骤,爬虫程序一般分为以下几步: 1. 明确爬虫需求 1.1 需求分析2. 选择爬虫框架 2.1 框架简介3. 编写爬虫程序 3.1 抓取网页数据 3.2 清洗网页数据(通过规则获取网页数据) 3.3 保存数据 1. 明确爬虫需求本文需要爬取的网站是:http://www.jandan.net/ooxx 需要爬取的内容是:爬取该网站的美女图片。 1.1 需求分析首先我们打开需要爬取的网站,选中一张美女图片,点击鼠标右键,选中检查,查看这张图片在html页面的位置。打开浏览器xpath-helper插件(没安装该插件可以通过浏览器应用安装),如下图所示: 通过使用xpath语法进行规则匹配,查找到我们想要的资源图片。同时我们也需要爬取下一页的图片数据,通过xpath语法找到下一页的url,加载下一页数据。所以我们需要采用递归的方式一页一页的爬取图片数据。 2. 爬虫框架的选择本文采用Python3.6版本开发环境。 网络请求框架使用:urllib html页面解析框架使用:lxml和xpath语法 最后将爬取的数据保存到本地文件。 2.1 框架简介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,https,返回的是一个http.client.HTTPResponse对象。 HTTPResponse对象 HTTPResponse对象,将响应的数据封装起来,常用的方法有: response.geturl():返回检索资源的URL,通常用于确定是否遵循重定向 response.code():返回的是响应码 response.msg:返回的是响应信息 response.info():返回的是响应头信息 response.read():读取响应的数据,响应体详细API可看下面官方文档: urllib官网文档 HTTPResponse官网文档 lxml类库和xpath语法 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官方文档 xpath语法文档 3. 编写爬虫程序我们明确需求,选择好框架后,就开始编写爬虫程序了,我们将爬虫程序分为3步,抓取数据,清洗数据,保存数据。 为了代码能很好的复用,我们把它封装成一个类JanDanSpider。定义3个方法,load_page() , parse_page() , load_image(), 如下: class JanDanSpider(object): def __init__(self): pass def load_page(self): pass def parse_page(self): pass def load_image(self): pass 3.1 抓取网页数据通过urllib.request模块,请求url链接,返回响应的内容。因为我们需要递归解析页面,以及加载图片,所有将请求的方法提取出来,封装成一个get_response()方法,具体如下: import urllib.request class JanDanSpider(object): def __init__(self): pass def get_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 3.2 清洗网页数据当我们获取网页返回的响应数据,接下来就是使用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 3.3 保存数据最后获取的数据,是图片的url链接,我们需要将url链接下载对应的图片,并保存到本地。 class JanDanSpider(object): def load_image(self, image_url): """ 下载图片 :param image_url: 图片的url :return: """ with open(self.create_filename(image_url), 'wb')as f: f.write(self.get_response(image_url)) def create_filename(self, image_url): """ 通过图片的url来确定存储路径 :param image_url: 图片的url :return: """ results = image_url.split('/') if 'large' in image_url: filename = 'image/large/' + results[-1] else: filename = 'image/normal/' + results[-1] return filename最后我们调用爬虫程序,然后运行: if __name__ == 'main': # 爬取的网站 url = "http://jandan.net/ooxx" spider = JanDanSpider() spider.load_page(url)运行输出的图片url,如图: 具体代码,可参见我的github , GitHub项目地址。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |