Python网络爬虫requests、bs4爬取空姐网图片
来源:互联网 发布:dynamodb编程 编辑:程序博客网 时间:2024/04/29 07:05
如之前的几篇文章(Python爬虫框架之Scrapy详解、Python爬虫框架Scrapy之爬取糗事百科大量段子数据),使用了Scrapy框架并且爬取了糗事百科的段子存入MongoDB中。
Scrapy框架很好,也提供了很多扩展点,可以自己编写中间件处理Scrapy的Request和Response。但是可定制化或者可掌控性来说,还是自己写的爬虫更加强一些。
如果写简单更加可控的爬虫,还是建议使用Python第三方库:requests和bs4。
requests和bs4爬空姐网图片
requests
requests是Python非常流行的处理网络数据的第三方库。相对于Python内置框架urllib、urllib2来说,requests提供的操作更加简洁而且更加丰富。如requests示例:
#HTTP请求类型#get类型r = requests.get('https://github.com/timeline.json')#post类型r = requests.post("http://m.ctrip.com/post")#put类型r = requests.put("http://m.ctrip.com/put")#delete类型r = requests.delete("http://m.ctrip.com/delete")#head类型r = requests.head("http://m.ctrip.com/head")#options类型r = requests.options("http://m.ctrip.com/get")#获取响应内容print r.content #以字节的方式去显示,中文显示为字符print r.text #以文本的方式去显示#URL传递参数payload = {'keyword': '日本', 'salecityid': '2'}r = requests.get("http://m.ctrip.com/webapp/tourvisa/visa_list", params=payload) print r.url #示例为http://m.ctrip.com/webapp/tourvisa/visa_list?salecityid=2&keyword=日本#获取/修改网页编码r = requests.get('https://github.com/timeline.json')print r.encodingr.encoding = 'utf-8'#json处理r = requests.get('https://github.com/timeline.json')print r.json() #需要先import json #定制请求头url = 'http://m.ctrip.com'headers = {'User-Agent' : 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19'}r = requests.post(url, headers=headers)print r.request.headers#复杂post请求url = 'http://m.ctrip.com'payload = {'some': 'data'}r = requests.post(url, data=json.dumps(payload)) #如果传递的payload是string而不是dict,需要先调用dumps方法格式化一下#post多部分编码文件url = 'http://m.ctrip.com'files = {'file': open('report.xls', 'rb')}r = requests.post(url, files=files)#响应状态码r = requests.get('http://m.ctrip.com')print r.status_code#响应头r = requests.get('http://m.ctrip.com')print r.headersprint r.headers['Content-Type']print r.headers.get('content-type') #访问响应头部分内容的两种方式#Cookiesurl = 'http://example.com/some/cookie/setting/url'r = requests.get(url)r.cookies['example_cookie_name'] #读取cookiesurl = 'http://m.ctrip.com/cookies'cookies = dict(cookies_are='working')r = requests.get(url, cookies=cookies) #发送cookies#设置超时时间r = requests.get('http://m.ctrip.com', timeout=0.001)#设置访问代理proxies = { "http": "http://10.10.10.10:8888", "https": "http://10.10.10.100:4444", }r = requests.get('http://m.ctrip.com', proxies=proxies)
通过requests,我们可以很方便的发送GET、POST、DELETE、PUT请求,获取相应数据等等。
bs4
bs4是指BeautifulSoup 4.x版本。相对于BeautifulSoup 2.x和3.x,4.x提供了更加丰富和人性化的api。使用BeautifulSoup,我们可以很方便的定位到HTML中我们想要的元素,获取元素值等等。如:
soup.title# <title>The Dormouse's story</title>soup.title.name# u'title'soup.title.string# u'The Dormouse's story'soup.title.parent.name# u'head'soup.p# <p class="title"><b>The Dormouse's story</b></p>soup.p['class']# u'title'soup.a# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>soup.find_all('a')# [<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>]soup.find(id="link3")# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
查看空姐网网页结构
首先,我们查看一下空姐网的网页结构,找到每个人的相册页面。在kongjie.com里面随意翻翻,就能找到热门相册页面,如图:
首先,分析一下该页面结构,提取出每个人的相册页链接。如图:
class属性为ptw的div下,ul中的每一个li都是每个人的相册封面,通过提取li中的链接,就能进入每个人的相册。
开始爬取
提取相册链接
从上面这个页面提取每个人相册链接的css表达式为div.ptw li.d
。这样,我们就可以把这个表达式用在BeautifulSoup里面了。
如,
def parse_album_url(url): """ 解析出相册url,然后进入相册爬取图片 """ response = requests.get(url, headers=headers) soup = BeautifulSoup(response.text, 'lxml') people_list = soup.select('div.ptw li.d') for people in people_list: save_images_in_album(people.div.a['href']) # 爬取下一页 next_page = soup.select_one('a.nxt') if next_page: parse_album_url(next_page['href'])if __name__ == '__main__': parse_album_url(start_url)
现在,获取到了每个人的相册链接,接下来就是编写save_images_in_album()方法,进入每个人的相册里面抓取图片了。再提一下,再这里,我们提取完一页中每个人的相册链接之后,解析了网页里的“下一页”的链接,这样就能自动翻页抓取了。“下一页”链接的网页结构如下:
通过css表达式a.nxt
就能提取到这个下一页链接。
进入相册提取图片
要编写爬虫,我们还是获取一下浏览器访问这个页面时的Request Headers,这样,就能绕过一些简单的反爬虫手段。
然后,进入到相册内部,查看一下网页结构,如图:
我们得知,id为photo_pic,class为c的div里面,第一个超链接里面的img标签就是大图。所以,我们在这里提取这个链接。我们使用soup.find('div', id='photo\_pic', class\_='c')
定位到id为photo_pic、class为c的div,然后通过image_div.a.img[‘src’]就能拿到这个图片的链接了。
拿到一张图片的链接之后,我们需要切换到下一张图片。可以看到,大图下面最后面有个向右的箭头,这个是下一张图的按钮,我们获取这个按钮的链接,获取连接对应的css表达式为div.pns.mlnv.vm.mtm.cl a.btn[title="下一张"]
,然后就可以重复上面两个步骤爬取相册里面所有的照片了。
图片去重
在这里,我们怎么知道一个相册里的图片都爬取完成了呢?
我们使用redis来存放爬取了的图片id,如果一张图片id已存在redis中了,那么不爬取了,这样,我们就能很方便的知道一个相册是否爬取完了(相册中所有图片id都存在redis中了,就表示该相册爬取完了)。
因此,我们写出save_images_in_album()方法如下:
def save_images_in_album(album_url): """ 进入空姐网用户的相册,开始一张一张的保存相册中的图片。 """ # 解析出uid和picid,用于存储图片的名字 uid_picid_match = uid_picid_pattern.search(album_url) if not uid_picid_match: return else: uid = uid_picid_match.group(1) picid = uid_picid_match.group(2) response = requests.get(album_url, headers=headers) soup = BeautifulSoup(response.text, 'lxml') image_div = soup.find('div', id='photo_pic', class_='c') if image_div and not redis_con.hexists('kongjiewang', uid + ':' + picid): image_src = domain_name + image_div.a.img['src'] save_img(image_src, uid, picid) redis_con.hset('kongjie', uid + ':' + picid, '1') next_image = soup.select_one('div.pns.mlnv.vm.mtm.cl a.btn[title="下一张"]') if not next_image: return # 解析下一张图片的picid,防止重复爬取图片,不重复则抓取 next_image_url = next_image['href'] next_uid_picid_match = uid_picid_pattern.search(next_image_url) if not next_uid_picid_match: return next_uid = next_uid_picid_match.group(1) next_picid = next_uid_picid_match.group(2) if not redis_con.hexists('kongjie', next_uid + ':' + next_picid): save_images_in_album(next_image_url)
这里,我们从相册的url中,通过正则表达式:uid_picid_pattern = re.compile(r’.*?uid=(\d+).*?picid=(\d+).*?’)解析出用户id和每张图片的id。然后就可以用redis来去重了。
下载图片
在上面这个函数里,我们拿到了每张图片大图的链接,即image_src变量。然后我们就可以编写save_img()方法来保存图片了。如:
def save_img(image_url, uid, picid): """ 保存图片到全局变量save_folder文件夹下,图片名字为“uid_picid.ext”。 其中,uid是用户id,picid是空姐网图片id,ext是图片的扩展名。 """ try: response = requests.get(image_url, stream=True) # 获取文件扩展名 file_name_prefix, file_name_ext = os.path.splitext(image_url) save_path = os.path.join(save_folder, uid + '_' + picid + file_name_ext) with open(save_path, 'wb') as fw: fw.write(response.content) print uid + '_' + picid + file_name_ext, 'image saved!', image_url except IOError as e: print 'save error!', e, image_url
运行结果
最后,我们在命令行运行Python kongjiewang.py。看一下结果:
大功告成!
感兴趣的可以关注:
github地址:https://github.com/ychenracing/Spiders/tree/master/kongjie
喜欢的可以关注微信公众号:
参考
- 我自己的头条号:Python爬虫框架Scrapy之爬取糗事百科大量段子数据
- Python网络爬虫requests、bs4爬取空姐网图片
- 用 requests-bs4 爬取网络图片
- python:使用requests,bs4爬取mmjpg上的图片
- [Python 爬虫之路1] 爬取糗事百科(requests,bs4)
- 【Python爬虫系列】使用requests爬取图片
- requests和bs4的python爬虫入门
- python+requests+bs4 爬取暴走GIF图片
- python网络爬虫爬取图片代码
- Python requests爬虫爬取小说数据
- Python网络爬虫与信息提取-Day5-Requests库网络爬取实战
- python +requests 实现爬取百度图片
- Python可自动登录爬取图片的网络爬虫
- Python——网络爬虫(爬取网页图片)
- 爬虫:用requests和BeautifulSoup爬取网上图片
- Python3网络爬虫:requests爬取动态网页内容
- 利用bs4和requests爬取股票历史交易数据
- 用 requests 和 bs4 爬取世界大学排名数据
- requests-re-bs4 定向爬取股票信息
- CS Academy E.Triplet Min Sum(最近公共祖先 倍增法模板)
- endnote中文献分类消失的解决办法
- Structs2中request session application 对数据处理的三种方式
- Linux的PCI驱动分析
- Java IO学习笔记总结
- Python网络爬虫requests、bs4爬取空姐网图片
- C++/C++11中std::stack的使用
- 使用Faster-RCNN训练自己的训练集
- nginx反向代理配置
- Android错误集锦
- 99%的人都理解错了HTTP中GET与POST的区别(转自知乎)
- 约瑟夫问题(用数组实现循环链式)
- ISAP模版
- [阿里云服务之旅]初探阿里云服务器