爬虫理论知识

什么是爬虫

  • 爬取网页数据的程序 它是一门工具

网页特征

  • 每个网页都有不同的url(统一资源定位符)
  • 网页都由HTML语言构成
  • 都用HTTP/HTTPS协议传输

爬虫怎么爬取网页

  • 定位你要的url地址
  • 然后把网页地址下载下来
  • 提取有用的数据,如果有 有用的URL,那继续爬

为什么用python做爬虫

python:代码简单易懂,并且第三方的库也有很多,python自带的urllib网络呢请求???requests网络请求模块,网络解析库xpath,BeautifulSoup4,pyquery等等,还有成熟
高效稳定的爬虫框架scrapy(pyspider)等等,并且还支持分布式爬虫(scrapy-redis)框架

java:是python写爬虫的最大的竞争对手,java的发展周期长,生态圈都比较完善,也有很多第三方库的支持,java的代码量比较大,开发的成本比较高,后期维护也比较繁琐

php:php曾经被叫做世界上最好的语言(一般用来后端的),也可以用来写爬虫,但是对多任务的支持不太好,爬虫对效率要求比较高,所有一般不适用php写爬虫

c/c++:比较偏向于底层的语言,代码的运行效率高,学习的门楷非常高,代码成型比较慢.

七层协议

应用层 表示层 会话程 传输层 网络层 数据链路层 物理层

OSI七层协议的目的:实现不同的系统互联之间的数据通讯,实现数据的传输.

应用层:http/https
传输层:TCP/UDP
TCP:网络传输协议,面向连接的,长连接,传输的是数据流
,确保数据的安全性和完整性,但是数据传输的效率低
UDP:网络传输协议,是非面向连接的,短连接,传输的是数据包,
传输数据是不安全的,可能会造成数据的丢失,传输速度非???/p>

http(超文本传输协议,端口号是80):
实现从网络传输草文本数据到本地浏览器的传送协议

https(端口号是443):是http的安全版本,在http的基础上添加了一个
SSL(安全套接字层)层,用于web端的安全传送,在传输层
对网络连接进行加密,
1.构建了一个安全的数据传输通道.
2.保证网站的真实性和有效性

https协议需要有一个证书(CA证书):由专门的证书机构颁发的,
也可以自己生成,但是访问的时候会提示连接不安全

https协议需要有一个证书(CA证书):由专门的证书机构颁发的,
也可以自己生成,但是访问的时候会提示连接不安全

http的工作原理:

URL介绍:
URI:统一资源标志符
URN:统一资源名称
URL:统一资源定位符
URI是URN和URL的父类

URL的组成部分:

https://baike.baidu.com/item/OSI/5520?fr=aladdin

https://book.qidian.com/info/1004608738

https://book.qidian.com/info/1004608738#Catalog

get:只是用于从服务器获取数据,再url连接后面
可能会跟一些查询参数
post:向服务器端提交数据,数据会放在请求体中,
     一般用于添加或者修改数据
delete:用来删除数据
put:更新整个资源(用来做数据的更新)
patch:(更新资源)(局部数据的更新)

对比:get和post请求的区别
1.使用场景:get从服务器端获取数据,post请求向服务器端提交数据
2.安全性:get请求参数只拼接在url地址上,post请求会将参数放在
请求体中,(注意:不要误认为只要url地址后面添加了参数就是一个get请求)
3.get请求的url是有长度限制的,post的请求体中可以添加很多字段
Cookie和Session:目的保持会话
http请求是无状态的,每一次请求断开后,下一次请求就
认为是一个新的请求,为了维持请求状态就用到了Cookie
和Session

Cookie:保存在客户端的,记录信息确定用户的身份
Session:保存在服务端的,同样是记录信息确定用户身份

常见的请求状态码:

200:请求成功
3xx:重定向
    301:永久重定向
    302:临时重定向

4xx:客户端请求错误
    400:请求错误,服务器无法解析
    401:未授权,没有进行身份验证
    403:服务器拒绝访问
    404:访问的页面不存在
    405:请求方式不允许
    408:请求超时

5xx:服务端错误
    500:服务端内部错误
    501:服务器暂时不具备完成请求的功能
    503:服务器不可用

urllib

request

#1.发起请求:python自带的urllib???#request:是urllib最基本的http网络请求???
from urllib import request

#https://www.qidian.com/all

#https://www.qidian.com/all
# ?orderId=&style=1&pageSize=20
# &siteid=1&pubflag=0&hiddenField=0&page=1

#https://www.qidian.com/all
#?orderId=&style=1&pageSize=20
# &siteid=1&pubflag=0&hiddenField=0&page=2

#https://www.qidian.com/all
# ?orderId=&style=1&pageSize=20
# &siteid=1&pubflag=0&hiddenField=0&page=3

#发起请求

"""
url:设置目标url

data=None:默认为None,表示发起的是一个get请求,
        反之,不为None,表示发起的是一个post请求
        
timeout: 设置请求的超时时间(s)

cafile=None, 设置证书文件(一般不用)
capath=None, 设置证书文件路径(一般不用)

context=None, 一般设置为一个ssl的对象
(ssl._create_unverified_context()),
忽略未认证的CA证书(如果出现了ssl证书错误)
"""

url = 'https://www.qidian.com/all?orderId=&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=0&page=1'
#如果请求需要添加请求头,urlopen并没有headers参数来设置请求头
"""
url:设置目标url 
data=None,:默认为None,表示发起的是一个get请求,
        反之,不为None,表示发起的是一个post请求
headers={}:设置请求头,传递一个字段类型的参数
"""
req_header = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
#根据url构建一个请求对象
req = request.Request(url=url,headers=req_header)
#使用urlopen方法faqi请求,获得响应结果
response = request.urlopen(req,timeout=20)
# response = request.urlopen(url=url,timeout=20)
#从响应结果中获取相关数据
# print(response.read())
html = response.read().decode('utf-8')
print(len(html))
"""
文件读写模式:
r:打开一个文件,只有可读权限  rb:   r+:  rb+
w:打开一个文件,有写入的权限  wb:   w+:  wb+
a:打开一个文件,有追加权限    ab:   a+:  ab+:
"""
with open('quanshu.html','w') as file:
    file.write(html)

#获取响应的状态码
code = response.status
print(code)
#获取响应的响应头
response_headers = response.getheaders()
print(response_headers)
#获取某一个响应头参数
server = response.getheader('Server')
print(server)
#获取当前请求的url地址
current_url = response.url
print(current_url)
#获取请求的reason(如果成功返回的是OK)
reason = response.reason
print(reason)
#注意:response.read(),只可以读取一次

#https://www.baidu.com/s?wd=新年愿望

error

# error模块:在我们请求过程中,可能因为服务器错误,弱网环境...

# 造成请求失败,这时我们需要对这些错误进行异常处理,不然会造成代码崩溃

from urllib import request,error

'''

error.URLError:

产生的原因主要有:

    没有网络连接

    服务器连接失败

    找不到指定的服务器

有一个reason属性:返回错误的原因

'''

'''

error.HTTPError

    HTTP请求错误,比如未认证,页面不存在

    code:请求的状态码

    reason:返回错误的原因

    headers:返回响应头部

'''

import ssl



context = ssl._create_unverified_context()



# url = 'https://www.baidu.com/12345.htm'

url = 'https://www.qidian.com/all/nsacnscn.htm'



try:

    response = request.urlopen(url,timeout=0.01,context=context)

    print(response.status)

except error.HTTPError as err:

    print('HTTPError')

    print(err.code)

    print(err.reason)

    print(err.headers)

except error.URLError as err:

    print('URLError',err.reason)

parse

#parse:可以对url进行拆分,组合,编码,解码,拼接
from urllib import parse

#parse.urlencode():将字典类型的参数转为url编码格式
form_data ={
    'first': 'false',
    'pn': 2,
    'kd': '后端',
}
#get请求直接使用urlencode将参数转为url编码格式
form_data1 = parse.urlencode(form_data)
print(form_data1)
#post请求urlencode将参数转为url编码格式,然后使
# 用encode方法将字符串转为bytes类型
form_data2 = parse.urlencode(form_data).encode('utf-8')
print(form_data2)

# parse.parse_qs():将url编码格式的字符串转化为字典类型
#注意key对应的value是一个list
parmas = parse.parse_qs(form_data1)
print(parmas)

#parse.quote()将中文字符转为url编码的字符
key = '我的国'
result = parse.quote(key)
print(result)

#parse.unquote()将url编码的字符转换为中文字符
unquote_result = parse.unquote(result)
print(unquote_result)

#将不完整的url参照基类url,拼接完整
base_url = 'http://www.qidian.com/book/123456.html'
sub_url = '12345789.html'
full_url = parse.urljoin(base_url,sub_url)
print(full_url)

#parse.urlparse():将url进行拆分
base_url = 'http://www.qidian.com/book/123456.html'
result = parse.urlparse(base_url)
"""
ParseResult(
 scheme='http',:协议
 netloc='www.qidian.com', ip或域
 path='/book/123456.html', 路径
 params='', 参数
 query='', 查询参数(?后面拼接的参数)
 fragment='' : 锚点
 )

"""
print(result)
print(result.scheme)
#parse.urlunparse():将url的各个部分合并为一个完整的url
#scheme, netloc, url, params, query, fragment
url_datas = ('https','www.baidu.com','book','','wd=xxx','1234')
full_url = parse.urlunparse(url_datas)
print(full_url)

正则表达式

#正则的规则:

#单字符匹配

"""

. 除换行符之外的任意字符

\d 表示数字

\D 匹配非数字

\w 匹配单词字符[a-z,A-Z,0-9]

\W 匹配非单词字符

\s 匹配空白字符,空格,\n \t ...

\S 匹配非空白字符

^ 匹配以...开头

$ 匹配以...结尾

[0-9] => \d 匹配0-9

"""



#多字符匹配(贪婪匹配)

"""

* 匹配*前面的字符任意次数

+ 匹配+前面的字符至少1次

? 匹配?前面的字符0~1次

{n,m} 匹配{n,m}前面的字符n~m次

"""



#多字符匹配(非贪婪匹配)

"""

*?

+?

??

"""



#其他

"""

() 分组

| 逻辑或

\ 转义字符

"""



#re??橄碌姆椒?
import re



#re.compile():构建正则表达式对象

#re.match():从起始位置开始匹配,单次匹配,匹配到

#结果立即返回,反之,返回None

str = 'abcdebfga'

pattern = re.compile('b|e')





result = re.match(pattern,str)

if result:

    print(result.group())



# re.search():在整个字符串中进行匹配,单次匹配,匹配到结果

# 立即返回,反之,返回None

result = re.search(pattern,str)

print(result.group())



# re.findall():匹配出整个字符串中,所有符合正则规则的结果

# 返回的是一个列表(list)

result = re.findall(pattern,str)

print(result)



# re.finditer():匹配出整个字符串中所有符合正则规则的结果,

# 返回的是一个可迭代对象

result = re.finditer(pattern,str)

print(type(result),result)

for i in result:

    print(i,type(i))

    print(i.group())



# re.sub():根据正则表达式进行字符串替换

new_str = re.sub(pattern,'h',str)

print(new_str)



#re.split():根据正则表达式进行分割,得到的是一个list



result = re.split(pattern,str)

print(result)

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

推荐阅读更多精彩内容

  • 什么是爬虫? 就是一段自动抓取互联网数据的程序或脚本 网页的三大特性 1.每个网页都有自己唯一的URL地址(统一资...
    bda1a329d33d阅读 456评论 0 0
  • 爬虫: 平台或者机构不能够提供我们需要的数据,这时就需要爬虫工程师,根据需求从互联网上抓取数据? 什么是爬虫? 就...
    Stranger_I阅读 347评论 0 1
  • HTTP基本原理 URI、URL、URN(Uninform Resource) URI(Identifier):统...
    GHope阅读 2,073评论 2 26
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • 小小说是一种颇受读者欢迎的文学体裁,字数在1000字到3000字之间,篇幅短小,而又寓意深刻,可谓“尺水兴波澜”。...
    上官飞鸿阅读 2,258评论 33 27