老司机教你看妹子——你的第一个知乎爬虫(1)

老司机教你看妹子——你的第一个知乎爬虫(1)

你看着知乎上一个个的爆照贴,想着怎样能把这些图片都保存下来呢。

“啊,老师啊,有没有什么可以批量保存小姐姐的功能啊”

少年你听说过爬虫么,会写python么

“emmmm,老师我python装好了,3.6”

孺子可教,

走着

把大象放进冰箱里

“老师我知道,第一步打开冰箱门,第二第把大象放进去,第三步关上冰箱门”,这个冷笑话你已经听了无数遍了,已经学会抢答了。

保存小姐姐也只需要三步:

1.打开网页
2.找到图片
3.保存

你默默的打开了搜索引擎:“如何用python打开网页”,然后一堆urllib之类的内容宛如天书,你又默默的关闭了网页。

“老师,有没有什么人类也能懂得方法来打来网页啊”

Requests: HTTP for Humans

“老师,他们还有中文版文档诶”

STEP 1

安装了库,读了一会文档后,你写出了第一步需要的代码:

Python 代码(python3):

import requests
url='https://www.zhihu.com/question/20399991'
r = requests.get(url)
text= r.text

你心怀期待的跑了一下:


“老师,我把知乎的服务器搞挂了,你看500了!”

真的这样么,刚刚不好好的么?你换了浏览器结果发现浏览器里还好好的啊。

很明显,知乎服务器把你给骗了,而且它还很恶意的把你的连接挂了很久,刚刚那段代码会很久很久才跑出结果。

“难道说,它发现我是爬虫了?!”

对的

“怎么发现的呢?”

浏览器在发送请求的时候,通常会带上一个User-Agent,这个字符串里通常会包含操作系统信息和浏览器的一些信息。

所以网站才会知道你用的是Android还是iOS,Windows还是Mac,iPad还是iPhone,Chrome还是IE。

“哦,那我们现在的user-agent是啥呢”

默认的是"python-requests/1.2.0"

你打开了Chrome,找到了开发者工具,在Network一栏里,点开一条网络请求,从Request Headers里找到自己浏览器的UA

import requests
header = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
url='https://www.zhihu.com/question/20399991'
r = requests.get(url,headers=header)
text= r.text

这样看起来就是一个正常的Chrome浏览器在访问页面了

这下就拿到结果了。

STEP 2

你轻轻的在交互式窗口里输入了 print text,结果涌现出来的东西把你吓了一跳。

“这一坨HTML要怎么办啊,哪些是图片呢?我要去怎么解析他们啊”

“python how to parse html” 你在搜索栏里打下这行字

你熟练的点开了 Stack Overflow的那个连接,准备复制黏贴,高票回答让你去用一个Beautiful Soup之类的东西。

你默默的打开了煤气灶,准备煲汤...

stop.jpg

“我只想下载个图片啊,老师能不能简单点,你说话的方式简单点...”

你当然可以用类似Beautiful Soup 之类的库去解析HTML的页面结构,但是我们需求没那么复杂(等汤煲好天都亮了),我们就简单的写个正则来匹配下吧。

一个典型的图片链接地址是这样的,https://pic1.zhimg.com/v2-dfad0e20695394c5fe79bfa5ec9dd170_b.jpg(贴心的知乎做了全站https),观察下发现,用https://开头以.jpg结尾,中间任意字符,同时,为了避免匹配到类似https://a/c.jpg</img>https://d/f.jpg这样的结果,我们需做最短匹配。

最后拿到就拿到了这样一个式子https://[^\s]*?\.jpg

“那只有jpg,还有png\jpeg\gif呢?”

多匹配几次喽...

jpg = re.compile(r'https://[^\s]*?\.jpg')
jpeg = re.compile(r'https://[^\s]*?\.jpeg')
gif = re.compile(r'https://[^\s]*?\.gif')
png = re.compile(r'https://[^\s]*?\.png')
imgs=[]
imgs+=jpg.findall(text)
imgs+=jpeg.findall(text)
imgs+=gif.findall(text)
imgs+=png.findall(text)
STEP 3

“下载图片我会!把图片链接写到txt文件里,然后用迅雷下载!”

放过迅雷吧,写一个花不了多久的。

def download(url):
    req = requests.get(url)
    if req.status_code == requests.codes.ok:
        name = url.split('/')[-1]
        f = open("./"+name,'wb')
        f.write(req.content)
        f.close()
        return True
    else:
        return False

“然后是一个for循环,挨个下载,然后还能记录下哪些连接出错了”,你已经轻车熟路了。

errors = []
for img_url in imgs:
    if download(img_url):
        print("download :"+img_url)
    else:
        errors.append(img_url)
print("ERROR URLS:")
print(errors)

让我们运行一下,有图片了!

以及一坨错误的URL:


STEP 5 检查

“为什么有两份呢,还有些莫名其妙的小图片。”
你把这些图快速的撸了一遍,啊不,浏览了一遍,发现重复的图片基本以_r和_b结尾,而_r是原图,而以_l,_xs,_is,结尾的都是头像,这些没啥好看的。

“老师我发现了,错误的url除了https://pic4.zhimg.com/***_{size}.jpg之类以外,还有带转义符的,转义符导致我们的正则匹配出了问题,不是一个合法的url.”

“还有啊,这个图是不是少了点,这个问题可是有一个有700个回答呢”

***_{size}.jpg和一些转义符都是因为这些内容本来是要经过JS在浏览器渲染的,图少的原因则是因为,答案的加载是有分页的,网页上拉倒后面能看到“更多”的按钮。

稍稍修改下正则表达式,我们只要原图。

jpg = re.compile(r'https://[^\s]*?_r\.jpg')
jpeg = re.compile(r'https://[^\s]*?_r\.jpeg')
gif = re.compile(r'https://[^\s]*?_r\.gif')
png = re.compile(r'https://[^\s]*?_r\.png')

给download函数加一个文件夹的参数,把图片存在文件夹里,然后封装一个函数,就可以一次批量下载多个URL了。

urls=['https://www.zhihu.com/question/22212644','https://www.zhihu.com/question/22212644',
      'https://www.zhihu.com/question/31983868','https://www.zhihu.com/question/20399991']
for url in urls :
    fetch(url)
    

“具体要怎么写啊老师,诶老师你干嘛去啊...”

自己写,爆照贴有新回复了,我看图去...

Final

import os
import re
import requests
def download(folder,url):
    if not os.path.exists(folder):
        os.makedirs(folder)
    req = requests.get(url)
    if req.status_code == requests.codes.ok:
        name = url.split('/')[-1]
        f = open("./"+folder+'/'+name,'wb')
        f.write(req.content)
        f.close()
        return True
    else:
        return False

header = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}

errs=[]

def fetch(url):
    r = requests.get(url,headers=header)
    text= r.text
    imgs=[]
    jpg = re.compile(r'https://[^\s]*?_r\.jpg')
    jpeg = re.compile(r'https://[^\s]*?_r\.jpeg')
    gif = re.compile(r'https://[^\s]*?_r\.gif')
    png = re.compile(r'https://[^\s]*?_r\.png')

    imgs+=jpg.findall(text)
    imgs+=jpeg.findall(text)
    imgs+=gif.findall(text)
    imgs+=png.findall(text)


    errors = []

    folder = url.split('/')[-1]
    for img_url in imgs:
        if download(folder,img_url):
            print("download :"+img_url)
        else:
            errors.append(img_url)
    return errors

urls=['https://www.zhihu.com/question/22212644','https://www.zhihu.com/question/29814297',
      'https://www.zhihu.com/question/31983868','https://www.zhihu.com/question/20399991']
for url in urls :
    print(url)
    errs+=fetch(url)

print("ERROR URLS:")
print(errs)

End

“老师,那我们要怎样才能获取到完整的回答啊,以及怎么把小姐姐们和照片对应起来啊”

那是下次的内容啦

“那老师下次去哪里找你啊”

关注我就好啦。我的知乎,或者我的简书:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,332评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,930评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,204评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,348评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,356评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,447评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,862评论 3 394
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,516评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,710评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,518评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,582评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,295评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,848评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,881评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,121评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,737评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,280评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,354评论 25 707
  • 老司机教你看妹子——你的第一个知乎爬虫(2) 序 “老师快教我怎么才能获取完整图片?” 别急,还记得上回说的,设置...
    李大白很黑阅读 1,043评论 0 2
  • 凡人本科学的是核工程核技术,一毕业就转行做了产品经理。 以前的同学问我在做什么,我说产品经理,一般会得到两种声音:...
    PM凡人阅读 432评论 0 0
  • 很多中国人认为医生的诊疗就是为了开检查赚钱的。谁不能否认的一点是,医生素质是最高的。医疗行业中,博士、硕士数...
    阳妹儿阅读 202评论 2 1
  • 感恩 1.感谢刘春学长的分享 2.谢谢蒙蒙姐的指导 成长~学习 1.不要抱有侥幸心理 这个道理是我当时在软实力课...
    剑胆琴心007阅读 192评论 0 2