这是我第一次发博客,起因是今天看了一些爬虫的例子,了解了一下原理,然后便尝试着自己进行一次爬虫,虽然过程有些曲折,但结果还是很令我满足的。也许是心血来潮,突然就想把我第一次爬虫的经历发出来,于是就发了。
好了,废话不多说,直奔主题吧。
首先我直接在网上随便找了一个网站:摄图网(这个网站的图片几乎都有水印,看起来有点别扭),然后按F12查看元素,点击NetWork去寻找headers信息(要按下F5刷新页面)。
我在这里就获取了User-Agent信息。然后就可以获取这个页面了,具体代码如下:
def get_page():
'''
获取页面
:return:
'''
url = "http://699pic.com/"
i_headers = {
"User-Agent": "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 67.0.3396.99Safari / 537.36"
}
req = urllib.request.Request(url, headers=i_headers)
page = urllib.request.urlopen(req).read()
return page
那么怎么获取页面上的图片呢?我们可以看到该网站中间部分有着很明显的分类,而我就选择了下方截图为例的部分分类进行图片的捕获。任意点击一个分类,在右侧查看标签的属性,我们就可以看到这些分类的链接。
接下来我们要做的就是将这些链接添加到一个列表中保存。
htm = html.fromstring(page)
urls = [] # img路径
for img_page in htm.xpath('//div[@class="label-list clearfix"]/a/@href'):
if img_page[:4] == "http":
urls.append(img_page)
在这里说明一下为什么我还要判断href的开头呢,说多了都是泪,看图:
测试的时候遇到了问题,真的是万万没想到还有一些奇怪的超链接混了进来。还好我在测试的时候输出了每个href属性的值,这才发现问题所在。希望大家在爬虫的时候也多注意一些这些小的细节吧。
接下来我点击一个分类,跳转到该分类的页面,可以看到该页面内有很多图片,这些就是我们的目标了。这里我先找到了referer信息,防止被该网站识破(方法就像开头的一样,referer信息就在user_agent的上方)。
点击图片在右侧看到元素的属性,获取图片的路径。这里又遇到了一个坑,我第一次开开心心的下载了几张图片,结果失败了,打印src属性的值才发现输出的结果并不是图片上的src属性所显示的值,然后我灵机一动改成了获取data-original属性值去下载...结果就正确了,下载的图片都很正常。(很多网站的src都是无效的,真实且可获取的路径可能会放在real_src等属性内,需要大家仔细观察img周围的元素内容)。
这部分代码如下:
i_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4882.400 QQBrowser/9.7.13059.400",
"Referer": "http://699pic.com/?sem=1&sem_kid=33723&sem_type=1"
}
req = urllib.request.Request(url, headers=i_headers)
i_page = urllib.request.urlopen(req).read()
htm = html.fromstring(i_page)
# img_title = htm.xpath('//div[@class="list"]/a/img/@alt')
img_src = htm.xpath('//div[@class="list"]/a/img/@data-original') # 图片的src获取不到
到这里就万事大吉了,只要下载就行了,我为了节约时间做了限制,只下载了几张图片。
for src in img_src:
filename = dirname + "/" + str(num) + ".jpg" # 这里名字先随便起了
with open(filename, "wb") as img: # 二进制写文件
img.write(requests.get(src, headers=i_headers).content)
time.sleep(0.5)
num += 1
if num > 5:
break
在这里还是要说一下,写文件时要用二进制,不然会报错的。
我第一次爬虫,能做到这一步还是网站比较简单的原因了。爬虫这些图片不需要代理,也不需要其他复杂的处理。尽管如此这个例子还是很多地方不好,比如文件夹的名字我都没去按照分类命名(和图片一样直接数字代替了)。
完整代码如下:
import urllib.request
import requests
import os
import time
import shutil
from lxml import html
def get_page():
'''
获取页面
:return:
'''
url = "http://699pic.com/"
i_headers = {
"User-Agent": "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 67.0.3396.99Safari / 537.36"
}
req = urllib.request.Request(url, headers=i_headers)
page = urllib.request.urlopen(req).read()
return page
def get_image(page):
htm = html.fromstring(page)
urls = [] # img路径
for img_page in htm.xpath('//div[@class="label-list clearfix"]/a/@href'):
if img_page[:4] == "http":
urls.append(img_page)
k = 1
for url in urls:
dirname = os.path.abspath(".") + "/" + str(k) # 文件下载在项目路径下
if os.path.exists(dirname):
shutil.rmtree(dirname)
os.mkdir(dirname)
i_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4882.400 QQBrowser/9.7.13059.400",
"Referer": "http://699pic.com/?sem=1&sem_kid=33723&sem_type=1"
}
req = urllib.request.Request(url, headers=i_headers)
i_page = urllib.request.urlopen(req).read()
htm = html.fromstring(i_page)
# img_title = htm.xpath('//div[@class="list"]/a/img/@alt')
img_src = htm.xpath('//div[@class="list"]/a/img/@data-original') # 图片的src获取不到
num = 0
for src in img_src:
filename = dirname + "/" + str(num) + ".jpg" # 这里名字先随便起了
with open(filename, "wb") as img: # 二进制写文件
img.write(requests.get(src, headers=i_headers).content)
time.sleep(0.5)
num += 1
if num > 5: # 每个分类下载5张图片就结束
break
k += 1
if k == 3: # 这样做下载两个分类就结束
break
if __name__ == '__main__':
page = get_page()
get_image(page)