Python爬蟲(1)------爬取網站圖片
初學爬蟲的學習流程
環境
python 3.6
使用 urlib庫進行爬取內容
熟悉爬蟲
首先對百度進行爬取
# -*- coding: utf-8 -*-
import urllib.request
url = 'http://www.baidu.com'
resp = urllib.request.urlopen(url)
print(resp.read())
使用urllib.request的urlopen()方法訪問一個url。
輸入伺服器返回的內容。
b'<!DOCTYPE html>\n<!--STATUS OK--><title >\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\xa5\xe9\x81\x93</title>\n \r\n\r\n<style id="css_index" index="index" type="text/css">html,body{height:100%}\nhtml{overflow-y:auto}\nbody{font:12px arial;text-align:;background:#fff}\nbody,p,form ,ul,li{margin:0;padding:0;list-style:none}\nbody,form,#fm{position:relative}\ntd{text-align:left}\nimg{border:0}\na{color:#00c}\na:active{color:#f60}\ninput{border:0;padding:0}\n#wrapper{position:relative;_position:;min-height:100%}\n#head{padding-bottom:100px;text-align:center;*z-index:1}\n#ftCon{height:50px;position :absolute;bottom:47px;text-align:left;width:100%;margin:0 auto;z-index:0;overflow:hidden}\n.ftCon-Wrapper{overflow:hidden;margin:0 auto;text-align:center;*width:640px}\n.qrcodeCon{text-align:center;position:absolute;bottom:140px;height:60px;width:100%}\n#qrcode{display:inline-block;*float:left;*margin-top:4px}\n#qrcode .qrcode-item{float:left}\n#qrcode .qrcode-item-2{margin-left:33px}\n#qrcode .qrcode-img{width:60px;height:60px}\n#qrcode .qrcode-item-1 .qrcode-img{background:url(http://s1.bdstatic.com/r/www/cache/static/home/img/qrcode/zbios_efde696.png) 0 0 no-repeat}\n#qrcode .qrcode-item-2 .qrcode-img{background:url(http://s1.bdstatic.com/r/www/cache/static/home/img/qrcode/nuomi_365eabd.png) 0 0 no-repeat}\n@media only screen and (-webkit-min-device-pixel-ratio:2){#qrcode .qrcode-item-1 .qrcode-img{background-image:url(http://s1.bdstatic.com/r/www/cache/static/home/img/qrcode/zbios_x2_9d645d9.png);background-size:60px 60px}\n#qrcode .qrcode-item-2 .qrcode-img{background-image:url(http://s1.bdstatic.com/r/www/cache/static/home/img/qrcode/nuomi_x2_55dc5b7.png);background-size:60px 60px}}\n#qrcode .qrcode-text{color:#999;line-height:23px;margin:3px 0 0}\n#qrcode .qrcode-text a{color:#999;text-decoration:none}\n#qrcode .qrcode-text p{text-align:center}\n#qrcode .qrcode-text b{color:#666;font-weight:700}\n#qrcode .qrcode-text span{letter-spacing:1px}\n#ftConw{display:inline-block;text-align:left;margin-left:33px;line-height:22px;position:relative;top:-2px;*float:right;*margin-left:0;*position:static}\n#ftConw,#ftConw a{color:#999}\n#ftConw{text-align:center;margin-left:0}\n.bg{background-image:url(http://s1.bdstatic.com/r/www/cache/static/global/img/icons_5859e57.png);background-repeat:no-repeat;_background-image:url(http://s1.bdstatic.com/r/www/cache/static/global/img/icons_d5b04cc.gif)}
只貼出部分程式碼,可以看到爬取的內容是亂碼的。
# -*- coding: utf-8 -*-
import urllib.request
url = 'http://www.baidu.com'
resp = urllib.request.urlopen(url)
print(resp.read().decode('utf-8'))
對輸出進行utf-8的轉碼即可正常顯示。
爬取虎嗅網的熱文
為了使我們的爬蟲看起來更像是瀏覽器訪問的我們一般對請求新增請求頭資訊。
不然可能會得到 403 Forbidden的網頁資訊
req = urllib.request.Request(target_url)
req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36")
這裡添加了鍵為”User-Agent”的瀏覽器資訊。
獲取虎嗅首頁html
import urllib
import urllib.request
url = 'https://www.huxiu.com'
def get_html(target_url):
req = urllib.request.Request(target_url)
req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36")
response = urllib.request.urlopen(req)
return response.read().decode('utf-8')
html = get_html(url)
print(html)
獲得首頁的html,在瀏覽器中開啟爬取的html。
按下F12鍵進入開發者模式。
點選 1 處,然後點選網頁中的任何地方就能跳到該元素所在的程式碼處,我們可以清楚的看見有一些 li 標籤整齊的排列在其中。
可以發現每個 li 裡面div塊的css都是hot-article-img
利用BeautifulSoup庫來對爬取到的html頁面進行解析
def use_bs_get_list(html):
soup = BeautifulSoup(html, "html.parser") # use html.parser dissection
all_list = soup.select('.hot-article-img')
return all_list
hot_article_list = use_bs_get_list(html)
- 初始化BeautifulSoup(html頁面,解析器)。
- 利用 .hot-article-img 我們要找的div塊用的css名,BeautifulSoup能很便捷的幫助我們解析。
- 輸出得到的list。
<div class="hot-article-img">
<a href="/article/242516.html" target="_blank" title="忽如一夜朝鮮來">
<!--視訊和圖片保留一個-->
<img src="https://img.huxiucdn.com/article/cover/201805/03/070310664833.jpg?imageView2/1/w/280/h/210/|imageMogr2/strip/interlace/1/quality/85/format/jpg"/>
</a>
</div>
可以看到每一個class=”hot-article-img”的div塊以list的元素輸出。
解析list的每個item得到文章的img title url三個資訊
def get_hot_article_img_title(all_list):
hot_article = []
for news in all_list:
# get <a ....>....</a>
a_tag = news.select('a')
# a[0]['title'] is none
if len(a_tag) > 0:
# article href
try:
href = url + a_tag[0]['href']
except Exception:
href = ''
# article img url
try:
# get img tag(inside a tag) img tag's src
img_url = a_tag[0].select('img')[0]['src']
except Exception:
img_url = ''
try:
title = a_tag[0]['title']
except Exception:
title = 'none'
hot_article.append("href:" + href + '\n' + "title:" + title + '\n' + "img_url:" + img_url + '\n')
return hot_article
利用BeautifulSoup處理的list每一個項都是tag物件仍舊可以對其中的標籤元素進行選擇解析。
首先是得到div裡的a標籤應為有兩個a標籤所以我們選第一個也就是a_tag[0]。再利用a_tag[0][屬性名]去選擇a標籤內某個屬性的內容。
文章url在a標籤的href內,當然還要和虎嗅的官網url拼接,文章名在title內,而文章圖片的url是在a標籤內部的img標籤的src裡。
href:https://www.huxiu.com/article/242516.html
title:忽如一夜朝鮮來
img_url:https://img.huxiucdn.com/article/cover/201805/03/070310664833.jpg?imageView2/1/w/280/h/210/|imageMogr2/strip/interlace/1/quality/85/format/jpg
最後儲存的項是這樣的。
對網頁html規律分析是十分重要的。
網站圖片的爬取
爬取首頁列表
爬取熱門美女這個列表
url = "https://www.meitulu.com"
def get_html(target_url):
headers = {
"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko)",
"Accept - Encoding": "gzip, deflate, br",
"Referer": "https://www.meitulu.com/"
}
req = urllib.request.Request(target_url, headers=headers)
response = urllib.request.urlopen(req)
content = response.read()
# b'<!' b=31
if content[0] == 31:
buff = BytesIO(content)
f = gzip.GzipFile(fileobj=buff)
res = f.read().decode('utf-8')
return res
# picture details is not gzip
return content.decode('utf-8')
應為有網頁是用gzip壓縮的,所以這邊有個判斷。
獲得每個列表項的url
def get_xiaojiejie_list(html, parsing_rules):
xiaojiejie_list = []
soup = BeautifulSoup(html, "html.parser")
tat_list = soup.select(parsing_rules)
tat_list = tat_list[0].select('li')
for var in tat_list:
url = var.select('a')[0]['href']
name = var.select('img')[0]['alt']
xiaojiejie_list.append({'name': name, 'url': url})
return xiaojiejie_list
hot_gril_list = get_xiaojiejie_list(html, 'ul[class="hot_meinv"]')
在html內容裡獲取class為hot_meinv的ul標籤
構建元素項為字典型別(包含名字 和 對應的url)的list
{'name': '森下悠裡', 'url': 'https://www.meitulu.com/t/yuuri-morishita/'},
{'name': '鈴木愛理', 'url': 'https://www.meitulu.com/t/airi-suzuki/'},
{'name': '柏木由紀', 'url': 'https://www.meitulu.com/t/kashiwagi-yuki/'}
獲取相簿資訊
獲得了首頁每個小姐姐url之後迴圈進入
這裡只貼出一個的爬取方法。
可以看到每一個相簿的url都安安靜靜的放在這裡。
def go_to_photo_list(hot_girl_list):
for var in hot_girl_list:
path = 'picture/' + var['name']
if os.path.exists(path) is False:
os.mkdir(path, 777)
else:
continue
second_level_html = get_html(var['url'])
url_list = get_item_girl_img_list(second_level_html, 'ul[class="img"]')
根據每個小姐姐的名字建立資料夾,有過的就不爬了。
然後獲取小姐姐相簿頁的html。
這裡匯入一個os庫,用來對資料夾進行操作。
獲得class=img的ul標籤內所有的li並對其進行解析。
def get_item_girl_img_list(html, parsing_rules):
item_list = []
soup = BeautifulSoup(html, "html.parser")
tat_list = soup.select(parsing_rules)
tat_list = tat_list[0].select('li')
for var in tat_list:
url = var.select('a')[0]['href']
name = var.select('img')[0]['alt']
count = var.select('p')[0].text.split(' ')[1]
# count = var.select()
item_list.append({'name': name, 'url': url, 'count': count})
return item_list
經過BeautifulSoup的篩選tat_list中只有一個內容就是ul標籤及其裡面的內容所以我們取tat_list[0]中的所有li
再對每個li進行解析 得到圖片的url 相簿名 以及相簿中圖片的數量
最終tat_list中的內容
[<li>
<a href="https://www.meitulu.com/item/6991.html" target="_blank"><img alt="[VYJ] No.114 柏木由紀 四刊全集套圖[237]" height="300" src="https://mtl.ttsqgs.com/images/img/6991/0.jpg" width="220"/></a>
<p><span>16</span>圖片: 237 張(1280X960)</p>
<p>機構: <a class="tags" href="https://www.meitulu.com/t/vyj/" target="_blank">VYJ</a></p>
<p>模特: <a class="tags" href="https://www.meitulu.com/t/kashiwagi-yuki/" target="_blank">柏木由紀</a></p>
<p>標籤: <a class="tags" href="https://www.meitulu.com/t/ribenmeinv/" target="_blank">日本美女</a> <a class="tags" href="https://www.meitulu.com/t/qingchun/" target="_blank">清純</a> <a class="tags" href="https://www.meitulu.com/t/tianmei/" target="_blank">甜美</a> <a class="tags" href="https://www.meitulu.com/t/meishaonv/" target="_blank">美少女</a> <a class="tags" href="https://www.meitulu.com/t/mengmeizi/" target="_blank">萌妹子</a></p>
<p class="p_title"><a href="https://www.meitulu.com/item/6991.html" target="_blank">[VYJ] No.114 柏木由紀 四刊全集套圖</a></p>
</li>, <li>
<a href="https://www.meitulu.com/item/6980.html" target="_blank"><img alt="[VYJ] No.111 柏木由紀 Yuki Kashiwagi [22]" height="300" src="https://mtl.ttsqgs.com/images/img/6980/0.jpg" width="220"/></a>
<p><span>11</span>圖片: 22 張(1280X960)</p>
<p>機構: <a class="tags" href="https://www.meitulu.com/t/vyj/" target="_blank">VYJ</a></p>
<p>模特: <a class="tags" href="https://www.meitulu.com/t/kashiwagi-yuki/" target="_blank">柏木由紀</a></p>
<p>標籤: <a class="tags" href="https://www.meitulu.com/t/qingchun/" target="_blank">清純</a> <a class="tags" href="https://www.meitulu.com/t/tianmei/" target="_blank">甜美</a> <a class="tags" href="https://www.meitulu.com/t/ribenmeinv/" target="_blank">日本美女</a> <a class="tags" href="https://www.meitulu.com/t/mengmeizi/" target="_blank">萌妹子</a></p>
<p class="p_title"><a href="https://www.meitulu.com/item/6980.html" target="_blank">[VYJ] No.111 柏木由紀 Yuki Kashiwagi </a></p>
</li>, ......
li標籤為list每個元素項
接下去是對list中每個item標籤的解析
for item in url_list:
img_html = get_html(item['url'])
print('now we go to url:' + item['url'])
get_img(img_html, count, item['url'], var['name'], item['count'])
print('above name is:' + item['name'])
count = count + 1
進如相簿爬取圖片。
爬取圖片
第二頁第三頁等等,相簿內之後的頁數只要利用首頁的url+”_頁數”就好了。
def get_img(img_html, count, img_url, girl_name, img_count):
img_count = int(img_count)
img_list = []
i = 0
page = 2
path = 'picture/' + girl_name + '/' + str(count)
if os.path.exists(path) is False:
os.mkdir(path, 777)
target_url = img_url
target_url = target_url[:-5] + '_' + str(page) + '.html'
while i < img_count:
soup = BeautifulSoup(img_html, "html.parser")
img_url_list = soup.select('center')[0].select('img')
for var in img_url_list:
a = var['src']
i = i + 1
img_list.append(a)
if i < img_count:
# print(target_url)
# i = 38 but img_count = 40 but img only 38 so break
try:
img_html = get_html(target_url)
except urllib.error.HTTPError:
break
page = page + 1
target_url = target_url.split("_")[0] + "_" + str(page) + ".html"
save_img(img_list, path)
def save_img(img_list, path):
count = 0
for item in img_list:
if os.path.exists(path + '/' + str(count) + ".jpg") is False:
f = open(path + '/' + str(count) + ".jpg", 'wb')
headers = {
"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko)",
"Accept - Encoding": "gzip, deflate, br",
"Referer": "https://www.meitulu.com/"
}
req = urllib.request.Request(item, headers=headers)
try:
response = urllib.request.urlopen(req)
except urllib.error.HTTPError:
print('error again')
f.close()
save_img(img_list, path)
else:
if (response.status > 199 and response.status < 300):
try:
f.write(response.read())
except Exception:
print('save file error')
f.close()
count = count + 1
print('success')
得到每張圖片的url 爬下來儲存到本地對應的資料夾中就好了。
文章從簡到繁,雖然講解不是特別細緻,但主要是體現一下學習流程,關鍵還是自己的體會。程式碼