爬虫学习(一)

正文共: 7739字 5图 预计阅读时间: 20分钟

每日分享

The happiness of this life depends less on what befalls you than the way in which you take it.

生活中的幸福不在于发生在你身上的事,而在于你应对事情的方法。

小闫语录

很久以前,听过这样一个故事:

有两个人在穿越沙漠,到了中段的时候,一个人拿着自己的半瓶水说:唉,就剩下半瓶水了。(此处省略无尽的感叹生活的不公,各种抱怨之类的......)。另一个拿着自己的半瓶水说:哇,还有半瓶水呢。

瞧,同样的半瓶水,相同的处境,一个人感觉到幸福,一个人各种负面能量。其实就是这样,看到一个人幸福,并不一定是他比我们拥有的更多,更多的是他对待生活的态度、方式。

最后送给大家一个段子:

一个人开着玛莎拉蒂在等红灯,此时看到旁边骑着摩托的小哥特别开心,然后他打开车窗问道:你工资多少啊?小哥:3000啊。他又问:那你是怎么做到,拿着3000的工资过的这么开心的啊?小哥:因为我没有办法啊?

爬虫学习(一)

1.爬虫基础知识

1.1为什么要学习爬虫?

1.多掌握一种技能,做一个全方面的技术人员人才。

2.可以私人订制一个搜索引擎。搜索引擎本身就是爬虫。

3.大数据时代,数据分析的前提就是数据源,数据源来自于爬虫数据的抓取。

4.对于SEO从业者来说,可以更好的进行搜索引擎优化。

1.2爬虫的概念。

网络爬虫简单的来说就是自动地抓取互联网信息的一个程序或者简简单单的一段代码。网络爬虫又称为网页蜘蛛,网络机器人等。爬虫就是模拟客户端发送网络请求,接收请求对应的响应,一种按照一定的规则自动抓取互联网信息的一个程序。

扩展:只要是客户端(主要指的是浏览器)能做的事情,原则上,爬虫都能够做。网站上的一些付费数据,客户端都看不到,所以我们也是无法爬取的。比如付费音乐以及收费小说等。

1.3爬虫的用途。

主要用途:数据采集。

其他用途:(违法行为)

1.抢票或者抢购(抢票软件本身就是爬虫,比如官方放票一瞬间,票都没了,很多都是被各大公司的app爬完了)。

2.投票刷票(朋友圈里各种亲朋好友的投票连接,刷票也是可以用爬虫实现)。

3.短信轰炸(具体实现不详细介绍,因为是违法行为,为了更好的打击违法行为,我们可以了解一下具体思路。简单的一个思路就是网站注册时候,会有短信验证码,准备一批注册网站,将一个手机号放进去,就可以实现短信轰炸了。目前短信轰炸不好解决,因为短信验证码的形式有语音、短信、电话各种方式,很棘手)。

4.网络攻击(DDos)。

5.web漏洞扫描器

爬虫是一个灰色地带,法律既没有禁止又没有鼓励。作为爬虫工程师本身也是有风险的。

1.4爬虫的分类。

通用爬虫:通常指搜索引擎和大型web服务提供商的爬虫。

聚焦爬虫:针对特定网站的爬虫,定向的获取某方面数据的爬虫。

  • 累积式爬虫:从开始到结束,不断的爬取,过程中会进行去重操作。
  • 增量式爬虫:已下载网页采取增量式更新,只爬取新产生的或者已经发生变化网页的爬虫。
  • Deep web爬虫:具备某些权限才能看到的数据。

互联网构成:表层网、深网(具有一定权限才可以看到的数据)、暗网(一些非法数据交易、黑色地带)。

1.5采集数据的用途。

金融(根据获取的金融新闻数据等指定投资策略,进行量化交易)、旅游(根据各类信息来优化出行策略)、电商(根据商品信息做一个比价系统)、游戏(根据游戏论坛的数据调整游戏运营)、银行(根据个人交易信息,制作征信系统,贷款评级等)、招聘(职位信息)、舆情(各大论坛来看一下舆论导向)。

1.6爬虫的工作原理。

1.6.1搜索引擎原理

抓取网页 --> 数据存储 --> 预处理 --> 提供检索服务、网站排名

尽可能多的抓取数据。

通用搜索引擎的局限性

1.通用搜索引擎所返回的网页里大多数的内容都是无用的。

2.中文搜索引擎自然语言检索理解困难。

3.信息占有量和覆盖率存在局限。

4.搜索引擎最主要的还是以关键字搜索为主,对于图片、数据库、音频视频多媒体的内容通用搜索引擎无能为力。

5.搜索引擎的社区化和个性化不好。没有根据请求用户的地域、性别因素等进行信息过滤。

6.搜索引擎抓取动态网页效果不好。

1.6.2聚焦爬虫原理

URL list --> 响应内容(--> 提取URL --> URL list) --> 提取数据 --> 入库(保存数据)

专业性强的,针对特定数据进行数据的爬取。

1.7ROBOTS协议

什么是Robots协议?

答:也称为爬虫协议、机器人协议。全称是网络爬虫排除标准。网站通过robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不可以爬取。

只是一个君子协议,道德层面的约定。没人或者没法律法规具体的规范,强制实施。

存在位置:robots.txt文件应该放置在网站的根目录下。

2.HTTP和HTTPS复习内容

2.1HTTP和HTTPS

HTTP是超文本传输协议(W3C预定义的,制定好各种标签。XML可扩展标记语言),默认端口号是80。

文本是线性存储的;超文本是链式存储的(字典)

HTTPS是HTTP+SSL(安全套接字层),默认端口是443。

HTTP和HTTPS属于应用层。 HTTPS比HTTP更安全,但是性能更低。

2.2http的请求过程

2.2.1请求过程中注意的一些点

url中#代表的是锚点:跳转到网页的指定锚点位置。比如打开一个网页,我们直接看到的是网页的顶部,还是中部,或者某一块数据的地方。 查询字符串是url中?之后,由=进行传值,由&进行隔开。

1.浏览器对URL进行编码。ASCII编码格式,不是Unicode。不能在URL中包含任何非ASCII字符。

2.浏览器访问一个网站,在获取网站源码之后,会根据源码上的链接加载图片、js、css文件等,我们称之为渲染,而爬虫只会请求源码。

XHR是XMLHTTPRequest,是ajax请求的原理,一个工具箱。 写爬虫要以浏览器开发者模式中Network中的数据包为准。

3.HTTP请求报文的格式。

4.HTTP常见的请求头。

url地址中q指的是权重,最大为1.

Content-Type、Host (主机和端口号)、Connection (链接类型)、Upgrade-Insecure-Requests (升级为HTTPS请求)、User-Agent (操作浏览器版本内核,爬虫中必须有且重点关注,用来伪装成浏览器。)、Referer (页面跳转处,表示从哪个页面跳转过来的,用于防爬和防盗链)、Cookie (Cookie用于进行状态保持,通常也用于识别用户身份,HTTP是无状态的)、Authorization(用于表示HTTP协议中需要认证资源的认证信息,如前边web课程中用于jwt认证)。

URL:统一资源定位符。一个url指的是具体的一个资源数据的地址。 URI:统一资源标识符。URI属于URL的父类,URL是URI的一个子集。 二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源(http://)。

5.get和post区别

5.1post更安全,用来传输实体数据,本质上更专业。当然post也是可以在URL地址中传递参数。get由url中传递数据。

5.2get是请求资源,post是浏览器向服务器提交数据。

5.3get中url有长度限制,不是有http协议限制,而是由浏览器限制的。post传输数据大小没有限制。

5.4get没有请求体。

6.响应状态码。

200:成功。

302:跳转,新的url在响应的Location头中给出。

303:浏览器对于POST的响应进行重定向至新的url。

307:浏览器对于GET的响应重定向至新的url。

403:资源不可用;服务器理解客户的请求,但拒绝处理它(没有权限)。

404:找不到该页面。

405:方法不允许。

500:服务器内部错误。原因:代码出现问题;调用第三方接口时出现问题。

503:服务器由于维护或者负载过重未能应答,在响应中可能可能会携带Retry-After响应头;有可能是因为爬虫频繁访问url,使服务器忽视爬虫的请求,最终返回503响应状态码。

7.response中Last-Modeifed

记录了该响应上一次修改时间(静态页面)。

2.2.2尝试用自己的话描述完整的HTTP请求的过程。

1.浏览器在拿到域名对应的ip(DNS解析)后,先向地址栏中的url发起请求,并获取响应。

2.在返回的响应内容(html)中,会带有css、js、图片等url地址,以及ajax代码,浏览器按照响应内容中的顺序依次发送其他的请求,并获取相应的响应。

3.浏览器每获取一个响应就对展示出的结果进行添加(加载),js,css等内容会修改页面的内容,js也可以重新发送请求,获取响应。

4.从获取第一个响应并在浏览器中展示,直到最终获取全部响应,并在展示的结果中添加内容或修改————这个过程叫做浏览器的渲染

2.3浏览器大战了解一下

第一次浏览器大战是微软和网景公司的一场竞争。网景公司上世纪90年代独霸天下,后来微软乘势而上,更好的遵循了W3C的标准,添加了一些新功能,再加上微软强大的财力人力投入,微软胜出,网景公司将自己卖给了AOL公司。

但是事情也不是这么就结束了,后来网景公司公开了浏览器的源码,命名为Mozilla。并且基于Mozilla源码的FIrefox(火狐浏览器)首次登台。Mozilla是一个基金会,它创立了火狐。

第二次浏览器大战就不单单是二分天下了。这次还有新的浏览器加入到大战中。有挪威的Opera(也就是欧朋浏览器),还有中国的Maxthon(遨游浏览器)。

微软团队当初一千多人,欧朋浏览器据说团队只有几十人,而遨游浏览器只是中国的一个天才工程师的个人爱好,当然现在有团队维护了。

浏览器之战并没有结束,后来又有其他的浏览器参与进来,有谷歌浏览器和苹果的浏览器。

苹果的Safari和Google的Chrome共用Webkit引擎。苹果浏览器主要是移动端。

2.4字符串类型的区别转化

bytes:二进制。

互联网上数据都是以二进制的方式传输的。

str:unicode(万国码)的呈现形式。

UTF8是Unicode实现的一种格式,是Unicode的一种扩展补充。它是一种变长的编码格式。

str和bytes如何转化?

答:字符串数据使用encode方法转化为bytes。bytes类型数据通过decode转化为字符串类型数据。编码方式默认是utf-8,如果需要选定编码方式,编码方式解码方式必须一样,否则就会出现乱码。

3.requests

为什么要学习requests?

1.requests的底层实现就是urllib2.

2.requests在python2和python3中通用,方法完全一样,urllib2在python2和python3中名称不同。

3.requests简单易用。

4.requests能够自动帮助我们解压(gzip压缩等)网页内容。

requests的作用?

答:发送网络请求,返回响应数据。

3.1requests的简单使用

3.1.1相应对象的常用属性

test:把响应对象的str类型,text属性是requests模块发送请求后,对响应内容的推测。

content:响应对象的bytes类型,如果想要获取二进制数据,直接使用content。如果想要获取str类型,直接对对象content进行解码decode。

响应对象.content.decode()

content是二进制的数据,可以下载图片。推荐使用content.decode()获取html页面内容。

status_code:响应状态码。

request:响应中的请求信息。

headers:响应头信息。

request.headers:响应对应的请求头。

3.1.2发送带headers的请求

import requests
url = 'https://www.baidu.com'
headers = {"User-Agent": "..."}
# get中可以只填url地址,也可以指定headers
response = request.get(url,headers=headers)

如果发起请求的时候,没有User-Agent,那么爬到的一般是假数据。只有指定了请求头中的User-Agent后才能伪装成浏览器获取真实的数据。 User-Agent是为了伪装你是谁,代理ip是为了伪装你在哪。

3.1.3发送带请求参数的请求

import requests
url = 'www.baidu.com/s?wd=python'
headers = {"User-Agent": "..."}
# 此处的url已经带了参数
response = request.get(url,headers=headers)

# 发送请求,并传入参数,形参名称:params
kw={'wd':'北京'}
url1 = 'www.baidu.com/'
# 下面的语句会自动将url1变为'www.baidu.com/s?wd=北京'
response = request.get(url1,headers=headers,params=kw)

3.1.4下载图片

可以将网上的图片地址给复制下来,然后将程序中url设置为粘贴内容,按照之前的代码爬取,最后写入文件即可。

with open('文件名','wb') as f:
    f.write(resp.content)

注意使用wb二进制写入文件。然后直接content就可以,不要解码。

3.1.5案例-爬取贴吧指定页数html源码

需求:完成任意贴吧爬虫。获取指定页数,保存成文件。

实现步骤:以类的形式实现爬虫的功能

1.准备工作,请求的url地址,请求头信息

初始化函数 __init__,析构函数 __del__

2.发送请求,获取响应

3.解析数据,保存数据

4.提供入口函数

import requests
# 第三版:实现不同页面的抓取,并且实现不同贴吧的抓取
class Tieba:

    def __init__(self,name,page):
        self.name = name
        # {}占位符,利用format可以传字典/列表/字符串等
        self.url = 'https://tieba.baidu.com/f?kw={}&ie=utf-8&pn='.format(name)
        self.url_list = [self.url + str(p*50) for p in range(page)]
        # 拼接url地址,遍历page
        # for p in range(page):
        #     self.url + str(p*50)

        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36'
        }

    def get_data(self,url):
        resp = requests.get(url,headers=self.headers)
        return resp.content.decode()

    def save_data(self,data,index):
        # 定义文件名
        file_name =self.name + str(index) + '.html'
        with open(file_name,'w') as f:
                f.write(data)

    def run(self):
        for url in self.url_list:
            data = self.get_data(url)
            # 获取遍历url的索引
            index = self.url_list.index(url)
            self.save_data(data,index)


if __name__ == '__main__':
    import sys
    name = sys.argv[1]
    page = int(sys.argv[2])
    tieba = Tieba(name,page)
    tieba.run()

重点

1.掌握requests模块的使用。

2.熟悉面向对象过程。

3.2requests深入

3.2.1发送post请求

使用场景

1.登录注册(post比get更安全)。

绝大多数的登录会使用post请求,极少数网站任然在使用get请求进行登录。

2.向服务器传输的数据量比较多的时候,或者向服务器传输大文件。

语法

response = requests.post(url,data=data,headers=headers)

data形式是字典。

3.2.2案例-获取金山翻译的结果

需求:发送post请求,获取金山翻译的结果。

实现步骤

1.构造请求信息,url、user-agent。

2.发送请求,获取响应。

3.解析响应,把json数据转成字典,输出结果。

4.定义启动函数。

代码

import json
import requests
# 需求:发送post请求,获取金山翻译的结果
class King:

    def __init__(self,kw):
        self.url = 'http://fy.iciba.com/ajax.php?a=fy'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36'
        }
        self.datas = {
            'f':'auto',
            't':'auto',
            'w':kw
        }
    def get_data(self):
        resp = requests.post(self.url,headers=self.headers,data=self.datas)
        return resp.content.decode()
    # 问题:只能中文翻译英文,不能英文翻译中文,key错误
    # result = dict_data['content']['out']
    # 可以使用捕获异常的方式。
    def parse_data(self,data):
        dict_data = json.loads(data)
        # 从字典中提取数据
        try:
            result = dict_data['content']['out']
        except:
            result = dict_data['content']['word_mean'][0]
        print(result)

    def run(self):
        data = self.get_data()
        self.parse_data(data)

if __name__ == '__main__':
    king = King('python')
    king.run()

可以中文转英文,也可以英文转中文

重点:掌握post请求的发送,传入请求体data

优质文章推荐:

公众号使用指南

redis操作命令总结

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

项目重点知识点详解

难点理解&面试题问答

flask框架中的一些常见问题

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

重点内容回顾-DRF

Django相关知识点回顾

美多商城项目导航帖

项目重要技术点介绍

原文发布于微信公众号 - 小闫笔记(Pythonnote)

原文发表时间:2019-03-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券