忽發奇想,想把某個網站的個人介紹的照片和對應的名字爬下來,想正則式想了很久都沒想出來,大神指點用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)