爬取妹子图(requests + BeautifulSoup)
刚刚入门爬虫,今天先对于单个图集进行爬取,过几天再进行翻页爬取。
使用requests库和BeautifulSoup库
目标网站:妹子图
今天是对于单个图集的爬取,就选择一个进行爬取,我选择的链接为:http://www.mzitu.com/123114
首先网站的分析,该网站有一定的反爬虫策略,所以应对就是加入headers(目前是小白,目前不知道具体为毛这样做)
- Hostreferer = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
- 'Referer':'http://www.mzitu.com'
- }
- Picreferer = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
- 'Referer':'http://i.meizitu.net'
- }
前一个头作为请求网站,后一个头作为破解盗链使用
获得页面HTML代码
用requests库的get方法,加上Hostreferer
- def get_html(url):#获得页面html代码
- req = requests.get(url, headers=Hostreferer)
- html = req.text
- return html
获得图集名称以及图集最大页数
分析网页构成如图所示,图集名称包含在h2标签内,且该标签在整个HTML代码里有唯一的class="main-title",
而最大页数只是被span标签包含,无法通过属性来提取。所以提取图集名称采取标签名+属性名一起提取,而最大页数就采取将span标签全部找出,最大页数在span标签中第11位,
- def get_page_name(url):#获得图集最大页数和名称
- html = get_html(url)
- soup = BeautifulSoup(html, 'lxml')
- span = soup.findAll('span')
- title = soup.find('h2', class_="main-title")
- return span[10].text, title.text
获得图片url链接
分析页面内容,含有图片链接的img标签中有一个alt属性的值是跟图集名称相同,可以用这个来直接找到这个标签,当然也可以先找到div标签中的class属性是main-inage,再找到img的src属性,这里我就采用第一种方法。
- def get_img_url(url, name):
- html = get_html(url)
- soup = BeautifulSoup(html, 'lxml')
- img_url = soup.find('img', alt= name)
- return img_url['src']
将图片存入本地
得到图片url链接之后要讲图片存到本地,在请求图片url的时候要加入Picreferer,否则网站会认为你是一个爬虫,会返还给你一个盗链图
该方法传入的参数有3个,第一个是图片url,第二个当前图片的页数,用作创建文件,第三个是图集名称,在存储之前先创建了一个名称是图集名称的文件夹,这样就能将图片存入指定文件夹
- def save_img(img_url, count, name):
- req = requests.get(img_url, headers=Picreferer)
- with open(name+'/'+str(count)+'.jpg', 'wb') as f:
- f.write(req.content)
爬取一个图集完整代码
- import requests
- from bs4 import BeautifulSoup
- import os
- Hostreferer = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
- 'Referer':'http://www.mzitu.com'
- }
- Picreferer = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
- 'Referer':'http://i.meizitu.net'
- }
- def get_page_name(url):#获得图集最大页数和名称
- html = get_html(url)
- soup = BeautifulSoup(html, 'lxml')
- span = soup.findAll('span')
- title = soup.find('h2', class_="main-title")
- return span[10].text, title.text
- def get_html(url):#获得页面html代码
- req = requests.get(url, headers=Hostreferer)
- html = req.text
- return html
- def get_img_url(url, name):
- html = get_html(url)
- soup = BeautifulSoup(html, 'lxml')
- img_url = soup.find('img', alt= name)
- return img_url['src']
- def save_img(img_url, count, name):
- req = requests.get(img_url, headers=Picreferer)
- with open(name+'/'+str(count)+'.jpg', 'wb') as f:
- f.write(req.content)
- def main():
- old_url = "http://www.mzitu.com/123114"
- page, name = get_page_name(old_url)
- os.mkdir(name)
- for i in range(1, int(page)+1):
- url = old_url + "/" + str(i)
- img_url = get_img_url(url, name)
- #print(img_url)
- save_img(img_url, i, name)
- print('保存第' + str(i) + '张图片成功')
- main()
在main方法中先请求到图集的名称和最大页数,并且使用名称创建一个文件夹来存储图片。再从1到最大页数做一个for循环,
然后图片的每一页是 图集首页 + / + 当前页数,得到含有图片内容的url链接,后面就可以将得到图片存入本地。
爬取结果
文件夹名称即为图集名称,内部图片以页数作为文件名。
下面准备开始多个页面的爬取,先将前面爬取一个图集的方法进行封装
爬取一个图集
在进行爬取一个图集前先加入一个方法,在爬取图集名称的时候,由于名称的字符不限,所以可能出现含有文件夹中不能出现的一些字符,例如:/ \ : ? < > 等
所以需要将前面的代码进行修改,加入一个rename方法,将这些字符换成可行的字符。(在这里我就直接将这些字符去掉)
这里采用re库,将name中含有的非法字符换成空,可以看做直接去掉。
- import re
- def rename(name):
- rstr = r'[\/\\\:\*\?\<\>\|]'
- new_name = re.sub(rstr, "", name)
- return new_name
- def save_one_atlas(old_url):
- page, name = get_page_name(old_url)
- new_name = rename(name)
- os.mkdir(new_name)
- print("图集--" + name + "--开始保存")
- for i in range(1, int(page)+1):
- url = old_url + "/" + str(i)
- img_url = get_img_url(url, name)
- # print(img_url)
- save_img(img_url, i, name)
- print('正在保存第' + str(i) + '张图片')
- print("图集--" + name + "保存成功")
爬取一整页图集
- def get_atlas_list(url):
- req = requests.get(url, headers=Hostreferer)
- soup = BeautifulSoup(req.text, 'lxml')
- atlas = soup.find_all(attrs={'class':'lazy'})
- atlas_list = []
- for atla in atlas:
- atlas_list.append(atla.parent['href'])
- return atlas_list
分析一个页面中的url链接,发现如果找 target="_blank" 这一属性,则会产生很多多余的链接,所以我直接从字标签入手找到属性 class="lazy"的img标签,然后再在寻找到img标签的父标签中的href
- def save_one_page(start_url):
- atlas_url = get_atlas_list(start_url)
- for url in atlas_url:
- save_one_atlas(url)
将爬取一整夜图集进行封装,方便后续的翻页爬取
翻页爬取
分析页面url,发现每一页均是初始网址+page/+页数/
第一页是初始网址,但是页数为1的链接也是直接进入第一页,所以所有页的url就可以用以上通式改变页数进行遍历。
- start_url = "http://www.mzitu.com/"
- for count in range(1, 3):
- url = start_url + "page/" + str(count) +"/"
- save_one_page(url)
这里作为测试,所以只爬取前两页图集。改变range内的参数,即可改变爬取页数。
完整代码
- import requests
- from bs4 import BeautifulSoup
- import os
- import re
- Hostreferer = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
- 'Referer':'http://www.mzitu.com'
- }
- Picreferer = {
- 'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
- 'Referer':'http://i.meizitu.net'
- }
- def get_page_name(url):#获得图集最大页数和名称
- html = get_html(url)
- soup = BeautifulSoup(html, 'lxml')
- span = soup.findAll('span')
- title = soup.find('h2', class_="main-title")
- return span[10].text, title.text
- def get_html(url):#获得页面html代码
- req = requests.get(url, headers=Hostreferer)
- html = req.text
- return html
- def get_img_url(url, name):
- html = get_html(url)
- soup = BeautifulSoup(html, 'lxml')
- img_url = soup.find('img', alt= name)
- return img_url['src']
- def save_img(img_url, count, name):
- req = requests.get(img_url, headers=Picreferer)
- new_name = rename(name)
- with open(new_name+'/'+str(count)+'.jpg', 'wb') as f:
- f.write(req.content)
- def rename(name):
- rstr = r'[\/\\\:\*\?\<\>\|]'
- new_name = re.sub(rstr, "", name)
- return new_name
- def save_one_atlas(old_url):
- page, name = get_page_name(old_url)
- new_name = rename(name)
- os.mkdir(new_name)
- print("图集--" + name + "--开始保存")
- for i in range(1, int(page)+1):
- url = old_url + "/" + str(i)
- img_url = get_img_url(url, name)
- # print(img_url)
- save_img(img_url, i, name)
- print('正在保存第' + str(i) + '张图片')
- print("图集--" + name + "保存成功")
- def get_atlas_list(url):
- req = requests.get(url, headers=Hostreferer)
- soup = BeautifulSoup(req.text, 'lxml')
- atlas = soup.find_all(attrs={'class':'lazy'})
- atlas_list = []
- for atla in atlas:
- atlas_list.append(atla.parent['href'])
- return atlas_list
- def save_one_page(start_url):
- atlas_url = get_atlas_list(start_url)
- for url in atlas_url:
- save_one_atlas(url)
- if __name__ == '__main__':
- start_url = "http://www.mzitu.com/"
- for count in range(1, 3):
- url = start_url + "page/" + str(count) +"/"
- save_one_page(url)
- print("爬取完成")
这个程序能够爬取图片,但是效率太低,正在学习多进程,希望之后可以提高该程序的爬取效率。
我爬了3个多G的图片花了我接近4个小时,足以证明效率是真的低。
并且在爬取过程中出现一个问题,提示 你的主机中的软件中止了一个已建立的连接 ,这个问题还未找到解决方法,也未找明产生的具体原因。
这是我写的第一篇较长的博客,还有很多未完善的地方,希望大家见谅。
爬取妹子图(requests + BeautifulSoup)的更多相关文章
- Python协程爬取妹子图(内有福利,你懂得~)
项目说明: 1.项目介绍 本项目使用Python提供的协程+scrapy中的选择器的使用(相当好用)实现爬取妹子图的(福利图)图片,这个学会了,某榴什么的.pow(2, 10)是吧! 2.用到的知 ...
- Python3爬虫系列:理论+实验+爬取妹子图实战
Github: https://github.com/wangy8961/python3-concurrency-pics-02 ,欢迎star 爬虫系列: (1) 理论 Python3爬虫系列01 ...
- 使用requests+BeaBeautiful Soup爬取妹子图图片
1. Requests:让 HTTP 服务人类 Requests 继承了urllib2的所有特性.Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定 ...
- python爬取妹子图全站全部图片-可自行添加-线程-进程爬取,图片去重
from bs4 import BeautifulSoupimport sys,os,requests,pymongo,timefrom lxml import etreedef get_fenlei ...
- 猫眼电影爬取(二):requests+beautifulsoup,并将数据存储到mysql数据库
上一篇通过requests+正则爬取了猫眼电影榜单,这次通过requests+beautifulsoup再爬取一次(其实这个网站更适合使用beautifulsoup库爬取) 1.先分析网页源码 可以看 ...
- Python网络爬虫 | Scrapy爬取妹子图网站全站照片
根据现有的知识,写了一个下载妹子图(meizitu.com)Scrapy脚本,把全站两万多张照片下载到了本地. 网站的分析 网页的网址分析 打开网站,发现网页的网址都是以 http://www.mei ...
- Python 2.7和3.6爬取妹子图网站单页测试图片
1.url= http://www.mzitu.com/74100/x,2为1到23的值 2.用到模块 os 创建文件目录; re模块正则匹配目录名 图片下载地址; time模块 限制下载时间;req ...
- Python 2.7_爬取妹子图网站单页测试图片_20170114
1.url= http://www.mzitu.com/74100/x,2为1到23的值 2.用到模块 os 创建文件目录; re模块正则匹配目录名 图片下载地址; time模块 限制下载时间;req ...
- Python 爬取妹子图(技术是无罪的)
... import requests from bs4 import BeautifulSoup import os import sys class mzitu(): def html(self, ...
随机推荐
- Several ports (8005, 8080, 8009) required by Tomcat v8.5 Server at localhost are already in use. The server may already be running in another process, or a system process may be using the port. To sta
eclipse出现:Several ports (8005, 8080, 8009) required by Tomcat v8.5 Server at localhost are already i ...
- sql字段为datetime,插入''的时候默认为1900年
Microsoft SQL Server Database Engine 用两个 4 字节的整数内部存储 datetime 数据类型的值. 第一个 4 字节存储“基础日期”(即 1900 年 1 月 ...
- data-ng-disabled指令
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- css3中有关transform的问题
Transform属性应用于元素的2D或3D转换.这个属性允许你将元素旋转,缩放,移动,倾斜等.
- vue 修改框架less变量
以vant框架为例,vue项目以less作为css处理器: less/var-reset.less @import '~vant/lib/index.less'; // Color variables ...
- Python 学习笔记(七)Python字符串(四)
输入输出 输入函数 raw_input (Python3:input) >>> raw_input("请输入一个字母") #获取输入内容的一个函数 请输入一个字母 ...
- 虚拟内存设置(解决linux内存不够情况)
一. 虚拟内存介绍 背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级.所以,程序和数据如果在内存的话,会有非常快的读写速度.但是,内存的造价是要高于 ...
- Co. - Microsoft - Windows - Tomcat、JDK、MySQL通过 Inno 集成为exe部署包
需求 客户设备为Windows系统,需要部署公司产品,因此将Tomcat.JDK.MySQL.Java.war 打包整合成exe文件,Windows下一键部署安装. 最佳实践 1.下载免安装的mysq ...
- 针对 npm ERR! cb() never called! 问题
在开发项目安装依赖时(npm install) 往往会报 npm ERR! cb()never called!的错误 如图: 解决方法: 一.首先要以管理员模式打开cmd清除你的npm缓存 : np ...
- thinkphp3.2.3实现多条件查询实例.
$data = M("datainfo"); $projectsname = I('get.projectsname');//前台提交的模糊查询字段 // 查询条件 $where ...