初级python爬虫实战一——爬取下厨房首页高清图

1. 预备工作

在花了两天半时间研究学习了urllib,requests,bs4,lxml等库之后,准备开始一个简单的实战——爬取“下厨房”网站首页所有的高清大图。


下厨房首页

首先F12观察一下这些图片的真实地址:


F12观察任意图片地址

观察到img =之后有一个链接地址,直接访问该地址:

直接访问观察地址

显然这是一个小图,不是我要的高清图。再观察复制下来的链接
链接分析

不难发现,以@为界,链接可以分为前后两个部分。猜想前一部分是图片地址,后一部分则是对图片进行压缩的参数。试着删除@及其之后的部分,再访问。果然出现了一张高清大图。
高清大图真实地址

这下子基础部分基本弄清楚了,预备动作就到这里。

2. 开爬!

终于可以开始写我的第一只爬虫了,激动~

2.1 获取页面,解析结构

首先,通过requests发起请求

import requests
from lxml import etree

# 模拟浏览器访问
ua = 'Mozilla/5.0 ' \
     '(Windows NT 10.0; Win64; x64) ' \
     'AppleWebKit/537.36 (KHTML, like Gecko) ' \
     'Chrome/80.0.3987.116 Safari/537.36'
header = {'User-Agent': ua}
r = requests.get("http://www.xiachufang.com/", headers=header)
# r = requests.get("http://httpbin.org/", headers=header)

print(r.text)
et = etree.HTML(r.text)
data = et.xpath('//img/@src')
for i in range(len(data)):
    print(data[i])
print(len(data))

控制窗口的输出信息为:


控制台输出信息

可见一共输出了75个数据,但是其中包含很大一部分:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEXo6Og4/a9sAAAADUlEQVR42gECAP3/AAAAAgABUyucMAAAAABJRU5ErkJggg

这样的数据。显然这不是我想要的。打印r.text观察一下这些数据在页面中的位置。发现有

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEXo6Og4/a9sAAAADUlEQVR42gECAP3/AAAAAgABUyucMAAAAABJRU5ErkJggg" 
data-src="http://i1.chuimg.com/b7933e0a29d54c53aab854f3ea65c9f3_750w_750h.jpg@2o_50sh_1pr_1l_60w_60h_1c_1e_90q_1wh" 
alt="夏夏2013" 
width="60" 
height="60">

原来这些用户分享的图片,真实地址在“data-src”属性中,而非“src”属性。
查找所有的data-src

data = et.xpath('//img/@data-src')
for i in range(len(data)):
    # print(data[i])
    pass
print(len(data))

输出结果为25,也就是原本链接地址为src的被筛选掉了,那么怎么才能保存所有的图呢?
想到了一个比较low,但是可行的方案:

  1. 找到img标签中不包含data-src属性但包含src属性中的src值
  2. 找到img标签中包含data-src属性的data-src
  3. 合并前两步中得到的列表
    在代码中体现为:
et = etree.HTML(r.text)
# 1. 找到img标签中不包含data-src属性但包含src属性中的src值
data1 = et.xpath("//img[not(@data-src) and @src]/@src")
# 2. 找到img标签中包含data-src属性的data-src
data2 = et.xpath("//img/@data-src")
# 3. 合并前两步中得到的列表
img_list= data1 + data2
for i in range(len(img_list)):
    print(img_list[i])
    # pass

观察输出结果:


不完美的结果

结果列表中存在空项。解决办法当然是去除空项:

# 删除空元素
while '' in img_list:
    img_list.remove('')

再观察输出结果:


完美的结果

完美输出了69个图片链接。这一部分完成!

2.2 处理img_list列表

由预备结果中的分析可知,下一步要做的是对列表中每一项进行分割,只保留高清大图部分,删除后面的参数。也即,保留链接中@符号之前的部分。使用urllib中的parse对链接进行分析。
导入urlparse

from urllib.parse import urlparse
for img in img_list:
    o = urlparse(img)

关于urlparse的用法,这里用一个例子说明:

 o = urlparse.urlparse("http://www.google.com/search?hl=en&q=urlparse&btnG=Google+Search")

参数
o.scheme 'http'
o.netloc 'www.google.com'
o.path '/search'
o.params ''
o.query 'hl=en&q=urlparse&btnG=Google+Search'
o.fragment ''

故可以对列表进行下面的处理:

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
处理后的url

完美!

2.3 文件操作

有了真实的url,下面要做的就是下载图片并保存到本地了。使用文件操作,首先必须导入python内置的os模块。

import os

初始化文件夹,如果不存在就创建一个:

# 文件操作,初始化xiachufang_image文件夹
image_dir = os.path.join(os.curdir, 'xiachufang_image')
if not os.path.isdir(image_dir):
    os.mkdir(image_dir)

2.4 最后一步

遍历访问处理后的url,并且以filename保存。(二进制写入)

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    filepath = os.path.join(image_dir, filename)
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
    resp = requests.get(url)
    with open(filepath, 'wb') as f:
        # 二进制以块写入
        for chunk in resp.iter_content(1024):
            f.write(chunk)

基本没有问题,但是少下载了几个图。再优化一下:

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    filepath = os.path.join(image_dir, filename)
    if not os.path.isdir(os.path.dirname(filepath)):
        os.mkdir(os.path.dirname(filepath))
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
    resp = requests.get(url)
    with open(filepath, 'wb') as f:
        # 二进制以块写入
        for chunk in resp.iter_content(1024):
            f.write(chunk)

看看文件夹,已经全部保存,欣赏一下美食吧~


总览

大图1

大图2

大图3
大图4

大图5

成就感和食欲均满满

3. 完整代码

贴出完整代码

import os
from urllib.parse import urlparse
import requests
from lxml import etree

# 模拟浏览器访问
ua = 'Mozilla/5.0 ' \
     '(Windows NT 10.0; Win64; x64) ' \
     'AppleWebKit/537.36 (KHTML, like Gecko) ' \
     'Chrome/80.0.3987.116 Safari/537.36'
header = {'User-Agent': ua}
r = requests.get("http://www.xiachufang.com/", headers=header)

# 开始解析
et = etree.HTML(r.text)
# 1. 找到img标签中不包含data-src属性但包含src属性中的src值
data1 = et.xpath("//img[not(@data-src) and @src]/@src")
# 2. 找到img标签中包含data-src属性的data-src
data2 = et.xpath("//img/@data-src")
# 3. 合并前两步中得到的列表
img_list = data1 + data2
# 删除空元素
while '' in img_list:
    img_list.remove('')

# 文件操作,初始化xiachufang_image文件夹
image_dir = os.path.join(os.curdir, 'xiachufang_image')
# if not os.path.isdir(image_dir):
#     os.mkdir(image_dir)

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    filepath = os.path.join(image_dir, filename)
    if not os.path.isdir(os.path.dirname(filepath)):
        os.mkdir(os.path.dirname(filepath))
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
    resp = requests.get(url)
    with open(filepath, 'wb') as f:
        # 二进制以块写入
        for chunk in resp.iter_content(1024):
            f.write(chunk)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 这是MrKevin365天写作计划中第6天的写作内容。 明天就是大年30了,按照中国人的传统,明天意味着春节的开始...
    MrKevin阅读 145评论 0 0
  • 20190221 星期四 雾转晴 宝爸昨晚夜班,刚开学大宝表现还算积极,今早起来洗涮吃完饭等着我去送他...
    Ai哲朵花儿阅读 210评论 0 1
  • ——邓翼徐 最近对那刻画风情万种女人和四大家室兴衰的《红楼梦...
    D_eng阅读 713评论 0 3