爬虫初识之BeautifulSoup库的使用-爬取某图片站的image

news/2024/12/29 8:22:18/

知识背景:

beautifulsoup:是一款非常强大的工具,爬虫利器。“美味的汤,绿色的浓汤”。一个灵活又方便的网页解析库,处理高效,支持多种解析器。 利用它就不用编写正则表达式也能方便的实现网页信息的抓取。

lxml:是python的一个解析库,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高。(具体可参考:https://www.cnblogs.com/zhangxinqi/p/9210211.html (XPath:全称XML Path Language,即XML路径语言,是一门在XML文档中查找某部分位置信息的语言,最初是用来搜寻XML文档节点信息的,但是它同样适用于HTML文档的搜索。可参考:https://zhuanlan.zhihu.com/p/37177627 XPath的选择功能十分强大,它提供了非常简明的路径选择表达式,另外,它还提供了超过100个内建函数,用于字符串、数值、时间的匹配以及节点、序列的处理等,几乎所有我们想要定位的节点,都可以用XPath来选择。 XPath于1999年11月16日成为W3C标准,它被设计为供XSLT、XPointer以及其他XML解析软件使用,更多的文档可以访问其官方网站:https://www.w3.org/TR/xpath/

本次demo目的: 熟悉爬虫,爬取某网站的图片到本地以便无聊时赏心悦目~~~

准备工作:安装bs4库,因用到解析库lxml,so也要pip install下lxml模块。(sublime的python环境配置这里就不多做赘述)

参考用例:

<!DOCTYPE html>
<html><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/><title>测试bs4</title><meta name="description" content=""/><meta name="keywords" content=""/><link href="" rel="stylesheet"/>
</head>
<body><div><p>python</p></div><div class="song" >唐宋八大家<a href="http://www.song.com/" title="豪放派" target="_self"><p class='su'> <a href="" id='su'>苏轼</a></p><p>...</p><p>唐有韩柳,宋为欧阳、三苏和曾王</p></a><a href="" class="du" title="婉约派">李清照</a><p id='li'> <a href="" id='li'>千古第一才女李清照</a></p><img src="http://www.baidu.com/meinv.jpg" alt=""></div><div class="tang"><ul><li><b>生当作人杰,死亦为鬼雄</b></li><li><i>易安居士</i></li><li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li><li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li><li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li><li><a href="http://www.haha.com" id='feng'>凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li><li><a href="http://www.sina.com" class="du">杜甫</a></li><li><a href="http://www.dudu.com" class="du">杜牧</a></li></ul></div>
</body>
</html>
from bs4 import BeautifulSoup# 1.生成对象
soup = BeautifulSoup(open('soup_text.html', encoding='utf-8'), 'lxml')
print(soup.prettify())
print(type(soup))
print(soup)
# 标签选择器:通过这种soup.标签名查找,如果文档中有多个这样的标签,只能找到第一个符合要求的标签
print(soup.title.name)    # 获取名称
print(type(soup.title))
print(soup.head)
print(soup.p)
print(soup.div)
# 2.获取属性
# soup.a.arrts  # 获取a标签所有属性和值,返回一个字典
# soup.a.attrs['href']  # 获取href属性
# soup.a['href']  # 也可简写成这种
#上面两种方式都可以获取a标签的href属性值
print(soup.a['href'])
print(soup.a['title'])
print(soup.a['target'])
print(soup.a.attrs['href'])
#attrs可以传入字典的方式来查找标签,但是这里有个特殊的就是class,因为class在python中是特殊的字段,所以如果想要查找class相关的可以更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的标签属性可以不写attrs,例如id
print(soup.find_all(attrs={'id': 'li'}))
# 3.获取内容
# soup.a.text
# soup.a.get_text()
# soup.a.string  # 只能够获取文本,如果标签里还有标签就返回None,而前两个,可以获取所有文本内容
print(soup.a.get_text())
print(soup.div.text)
print(soup.div.string)
print(soup.div.get_text())
#嵌套选择
#我们直接可以通过下面嵌套的方式获取子节点和子孙节点
print(soup.head.title.string)
# 4.find
# soup.find('a')  #找到第一个符合要求的标签
# print(soup.find('a', title='qin'))
# print(soup.find('a', alt='qi'))
# print(soup.find('a', class_='du'))
# print(soup.find('a', id='feng'))
# print(soup.find('a', class_='du'))  # 注意使用class_,区别于类关键字
# div = soup.find('div', class_='tang')
# print(div)
# print(div.find('a', alt='qi'))
print(div.find('a', class_='du'))  # find方法不仅soup可以调用,普通的div对象也能调用,会去指定的div里面去查找符合要求的节点
# 5.find_all
lt = soup.find_all('a')
print('soup.find_all\'s type:', type(lt))
div = soup.find('div', class_='tang')
a = div.find_all('a')
# print(a)
print('soup.find().find_all\'s type:', type(a))  # <class 'bs4.element.ResultSet'>
print('soup.find().find_all element\'s type:', type(a[0]))  # <class 'bs4.element.ResultSet'>
# print(a[0].get_text('href'))
print(div.find_all(['a', 'b']))  # 返回列表内所有的标签内容
# print(div.find_all('a', limit=2))  # 取前两个# find、find_all返回列表,类型都为<class 'bs4.element.ResultSet'>,元素为<class 'bs4.element.Tag'>
# find_all(name,attrs,recursive,text,**kwargs)
# find(name,attrs,recursive,text,**kwargs)
# 可以根据标签名,属性,内容查找文档。
# find返回的匹配结果的第一个元素其他一些类似的用法:
# find_parents()返回所有祖先节点,find_parent()返回直接父节点。
# find_next_siblings()返回后面所有兄弟节点,find_next_sibling()返回后面第一个兄弟节点。
# # find_previous_siblings()返回前面所有兄弟节点,find_previous_sibling()返回前面第一个兄弟节点。
# find_all_next()返回节点后所有符合条件的节点, find_next()返回第一个符合条件的节点
# find_all_previous()返回节点后所有符合条件的节点, find_previous()返回第一个符合条件的节点# 6.select
s = soup.select('.song')
print(len(s))
print('soup.select\'s type:', type(s))        # 返回列表<class 'list'>
# print(s[0])
print('select\'s element type:', type(s[0]))     # <class 'bs4.element.Tag'>
s1 = soup.select('.song a')    # 组合查找,可层级筛选
print(s1)
print(s1[0].get('href'))
s2 = soup.select('.song img')
print(s2[0].get('src'))
# print(s2[0].get('alt'))
print(soup.select(' p #su'))    # 组合查找,p标签下id为su的内容
print(soup.select(' p.su'))    # 组合查找,class为su的p标签内容
print(soup.select('p#li'))    # 组合查找,id为li的p标签的内容
print(soup.select('head>title'))      # 直接子标签查找
# select返回列表,类型为<class 'list'>,list中元素为<class 'bs4.element.Tag'>

具体使用:

from bs4 import BeautifulSoup
#设置头部信息
...
headers={'cookie': cookie,      # 自行补充cookies'referer': referer,      # 跳转自的页面'user-agent': user_agent    # 伪装浏览器引擎
}
main_count = 1
# 获取具体图片所在url,并下载相应图片信息
def get_url(url, headers):global main_countprint('******主页第{}页,url:{}*****'.format(main_count, url))res = requests.get(url, headers=headers)soup = BeautifulSoup(res.text, 'lxml')div = soup.find('div', class_='main-content')   # 限定div,尽量缩小查找节点的范围,避免获取到垃圾url造成不必要麻烦for i in div.find_all(target='_blank'):if i.select('img'):img_url = i.get('href')print(img_url)# 获取图片get_second_parse(img_url, headers)time.sleep(2)# 由于网站图片集有分页,所以需要处理分页,获取下一图集所在url,并回调if soup.select('a.next.page-numbers')[0].get('href'):next_url = soup.select('a.next.page-numbers')[0].get('href')main_count += 1get_url(next_url, headers)# 获取具体图片所在url,并下载相应图片信息
def get_url(url, headers, img_num_per_page):global main_countprint('******主页第{}页,url:{}*****'.format(main_count, url))res = requests.get(url, headers=headers)soup = BeautifulSoup(res.text, 'lxml')div = soup.find('div', class_='main-content')    # 限定div,尽量缩小查找节点的范围,避免获取到垃圾url造成不必要麻烦for i in div.find_all(target='_blank'):if i.select('img'):img_url = i.get('href')print(img_url)# 获取图片get_inside_parse(img_url, headers, img_num_per_page)# breaktime.sleep(2)# 由于网站图片集有分页,所以需要处理分页,获取下一图集所在url,并回调if soup.select('a.next.page-numbers')[0].get('href'):next_url = soup.select('a.next.page-numbers')[0].get('href')main_count += 1get_url(next_url, headers, img_num_per_page)# 下载每张照片,注意单位时间访问服务器的频率防止被forbidden
def get_inside_parse(lst_url, headers, img_num_per_page):count = 1print('second_parse')res = requests.get(lst_url, headers=headers)time.sleep(1)try:img_title_soup = BeautifulSoup(res.text, 'lxml')if img_title_soup.select('.main-title')[0].get_text():img_title = img_title_soup.select('.main-title')[0].get_text()# print(img_title)for index in range(1, img_num_per_page):     # 最多下载到img_num_per_page-1张,可自行设置page_url = lst_url + '/' + str(index)res = requests.get(page_url, headers=headers)time.sleep(1)print(page_url, res.status_code)if res.status_code != 200:    # 超出图片列表,status错误则跳出breaksoup = BeautifulSoup(res.text, 'lxml')# 注意select的使用,select返回值类型:<class 'bs4.element.ResultSet'>列表if soup.select('.main-image p a img')[0].get('src'):img_url = soup.select('.main-image p a img')[0].get('src')filename = 'my_imgs/{}'.format(img_title)if not os.path.exists(filename):os.makedirs(filename)print('正在下载{}第{}张图片'.format(img_title, count))print(soup.select('.main-image p a img')[0].get('src'))print(filename)dirname = '%s/%s.jpg' % (filename, count)with open(dirname, 'wb+') as jpg:jpg.write(requests.get(img_url, headers=headers).content)time.sleep(1)count += 1else:print('URL:{}无main-title').format(lst_url)except ValueError as e:print(e.ValueError)if __name__ == '__main__':get_url(url, headers, 21)

  

过程问题:

  1. find、find_all返回列表,类型都为<class 'bs4.element.ResultSet'>,元素为<class 'bs4.element.Tag'>

  2. select返回列表,类型为<class 'list'>,list中元素为<class 'bs4.element.Tag'>

转载于:https://www.cnblogs.com/calmzone/p/11139980.html


http://www.ppmy.cn/news/561994.html

相关文章

python多张图叠加为一张_Python PIL实现图片重叠

入学前学校有个作业,想想可以搞点啥呢 于是就想着可以用PIL模块,把学校的风景和某些元素叠加起来 于是在网上搜寻了一些资料,看到的都是烂七八糟的,以及从其他地方COPY下来的 于是自己就找到了PIL模块的手册搞起来 图1 11.jpg 图2 22.jpg 这个程序的功能是实现两张图…

python图像识别之图片相似度计算

作者 | a1131825850疯子 来源 | Python爬虫scrapy 1.背景 要识别两张图片是否相似&#xff0c;首先我们可能会区分这两张图是人物照&#xff0c;还是风景照等…对应的风景照是蓝天还是大海…做一系列的分类。 从机器学习的的角度来说&#xff0c;首先要提取图片的特征&#…

职教云计算机考试上传图片,2017全国计算机等级考试报名关于上传图片须知

2017全国计算机等级考试报名关于上传图片须知 每年都会有部分考生由于对报考流程的不了解&#xff0c;造成报名失败&#xff0c;而图片上传不当是大家报名失败的最大原因。下面小编为大家整理了2017全国计算机等级考试报名关于上传图片须知&#xff0c;希望能帮到大家&#xff…

android 4.4 获取图片主色调,Android Lollipop:使用Palette抽取图片主色调

使用Palette抽取Bitmap主色调 关于Palette 一些Support库随着Android Lollipop的发布而诞生了,其中就有Palette。这个库可以让你很轻松地从一幅图中抽取特征颜色,这在你希望界面的颜色风格适应指定图片时非常有用,它还会提供与指定颜色相搭配的字体颜色。 Palette顾名思义调…

python识别图片中数字_Python Opencv识别两张相似图片

在网上看到python做图像识别的相关文章后&#xff0c;真心感觉python的功能实在太强大&#xff0c;因此将这些文章总结一下&#xff0c;建立一下自己的知识体系。 当然了&#xff0c;图像识别这个话题作为计算机科学的一个分支&#xff0c;不可能就在本文简单几句就说清&#…

python批量下载图片用多线程_简单使用python多进程并发下载大量图片

如果有大量图片想要下载&#xff0c;肯定希望速度越快越好&#xff0c;那么就要使用多任务。 python支持多线程和多进程。但是解释器中的GIL锁导致任何Python线程执行前&#xff0c;必须先获得GIL锁&#xff0c;然后&#xff0c;每执行100条字节码&#xff0c;解释器就自动释放…

python 使用 requests 库爬取百度图片脚本

# coding utf-8"""爬取百度壁纸图片 """/* 优秀开源电商系统学习地址&#xff1a;http://github.crmeb.net/u/fei */import requests,re,time,warnings,os warnings.filterwarnings("ignore")def search(key_word):# 百度获取风景壁纸…

python图片识别是否p过_Python+Opencv进行识别相似图片

标签:在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。 当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简单几句就说清,所以本文只作基本算法的科普向。 看到一篇博客是介绍…