忽发奇想,想把某个网站的个人介绍的照片和对应的名字爬下来,想正则式想了很久都没想出来,大神指点用beautifulsoup吧,挣扎了一段时间我觉得在这个问题上放弃正则式。(还是想要想出来)
问题描述
[li]
[a][img src="(url)" border="0"][/a]
[div]
[p][strong](name)[/strong][/p]
[p][/p]
[p][/p]
[/div]
[/li]
每个人的个人信息存在list里,首先是图片,其次是个人简介,一看特别简单,要爬的信息前后都有明显的标记。
src="(.*?) border"
和[strong](.*?)[/strong]
就能提出来了,但问题是我想让同一个人(同一个List)的信息存在一起,这样取姓名就很方便。
然鹅,我想来想去……想不出来,只能或出来,这并不是我想要的结果。
beautifulsoup
于是转战bs4,首先是安装有点小问题,直接pip install下不下来,只能去官网下安装包,放到python27/Scripts
里pip安装。
又然鹅,报错。
'module' object has no attribute '_base'
1.治标不治本的方法,复制C:\Python27\Lib\site-packages\html5lib\treewalkers\base.py
改为_base.py
放到C:\Python27\Lib\site-packages\bs4\builder
里,之后会其他报错……
ImportError: cannot import name '_htmlparser'
这个的解决方案是修改C:\Python27\Lib\site-packages\bs4\builder\__init__.py
文件,在文件的末尾,注释掉下面几行:
from . import _htmlparser
register_treebuilders_from(_htmlparser)
try:
from . import _html5lib
register_treebuilders_from(_html5lib)
except ImportError:
# They don't have html5lib installed.
pass
以上方法,又会出现没有parser的错误,不推荐。
2.根本问题是html5lib的版本过高,只要安装一个低于1.0的就可以解决。
pip install --upgrade html5lib==1.0
最后解决
利用beautifulsoup,很容易就能实现我们的要求。
先将html转换
soup = BeautifulSoup(html, 'html.parser')
里面的结构就会标准化了,直接find_all标签就可以提取一个块,针对每个块(每个memberlist)再提取每个人的头像url和姓名,扩展列表存进去。这样就是每人对应一行,第一列为url,第二列为名字。
for member in soup.find_all('li'):
img = member.find('img')
imgre = re.compile('src="(.*)"/')
imgurl = re.findall(imgre, str(img))
if len(imgurl) != 0:
name = member.find('strong')
namere = re.compile('<strong>(.*?)</strong>')
nameli = re.findall(namere, str(name))
memberlist.append([])
memberlist[i].append(imgurl)
memberlist[i].append(nameli)
i += 1
else:
pass
其中有两个点需要注意,图片的格式不一定相同,因此需要提取出来,将url按’.'分割,取最后一位的format。此外,在利用urlretrieve()函数存图片时,一直会报错,原因是我们爬的中文编码和存储的编码不一致,导致在open路径时报错,因此要将姓名解码成Unicode(将list转成string后,我们可以用chardet函数查看该字符串的编码)。
参考博客:urllib.urlretrieve(url, file_path) 保存中文名乱码
x = 0
for imginfo in memberlist:
imgformat = ''.join(imginfo[0]).split('.')
imgformat = ''.join(imgformat[-1])
imgcompurl = 'http://..../' + ''.join(imginfo[0])
fencoding = chardet.detect(''.join(imginfo[1]))
imgsave = ('../images/' + ''.join(imginfo[1]).decode('utf-8')+ '.' + imgformat)
#urllib.urlretrieve(imgcompurl, imgsave)