网络爬虫概论

网络爬虫概论

文章目录

    • 网络爬虫概论
      • 第1章 爬虫的作用:
      • 第2章 网页的三大特征:
      • 第3章 爬虫的流程:
      • 第4章 通用爬虫抓取网页的流程:
      • 第5章 通用爬虫的缺点:
      • 第6章 OSI七层协议:
      • 第7章 常见的请求状态码:
      • 第8章 发起请求:
      • 第9章 使用urllib发起请求:
      • 第10章 正则表达式:
      • 第11章 列子(re模块是python中处理正则表达式的一个模块)
      • 第12章 cookies的使用
      • 第13章 cookiejar的使用
      • 第14章 urllib.error的使用
      • 第15章 urllib的parse模块的使用
      • 第16章 urllib_proxy的使用
      • 第17章 requests模块
      • 第18章 resquests_post请求
      • 第19章 requests_outh
      • 第20章 requests下使用cookies
      • 第21章 使用requests模块设置代理
      • 第22章 requests.session的使用
      • 第23章 xpath的使用
      • 第24章 xpath常见的语法:

爬虫:网络爬虫机器人,从互联网自动抓取数据的程序
理论上:通过浏览器看到的数据,我们一般都是可以获取到的

第1章 爬虫的作用:

  • 1.1 搜索引擎
  • 1.2 商品比价(电商商品销售量统计分析)
  • 1.3 数据分析平台(豆瓣,知乎专栏等)

第2章 网页的三大特征:

  • 2.1 每一个网页都有一个唯一的url(统一资源定位符),来进行定位
  • 2.2 网页都是通过HTMl(超文本)文本展示的
  • 2.3 所有的网页都是通过http<超文本传输协议>(HTTPS)协议来传输的

第3章 爬虫的流程:

  • 3.1 分析网站,得到目标url
  • 3.2 根据url,发起请求,获取页面的HTML的源码
  • 3.3 从页面源码中提取数据
    • a. 提取目标数据,做数据的筛选和持久化存储
    • b. 从页面中提取到新的url地址,继续执行第二部操作
  • 3.4 爬虫结束:所有的目标url都提取完毕,并且得到了数据,再也没有其他请求任务了,这是意味着爬虫结束

第4章 通用爬虫抓取网页的流程:

  • 4.1 选取一部分的url作为种子url,将这些url放入到带爬取得任务队列里
  • 4.2 从带爬取得任务队列中取出url,发起请求,将获取到的页面源码存储到本地,并将已经爬取过的url,放入已爬取队列中
  • 4.3 从已爬取url的响应结果中,分析提取其他的url地址,继续添加到带爬取队列中,之后就是不断的循环,查到所有的url都提取完毕

第5章 通用爬虫的缺点:

  • 5.1 必须遵守roobot协议:就是一个规范,告诉搜索引擎,哪些目录下的资源允许爬虫,哪些目录下的资源不允许爬取
  • 5.2 ‘User-agent’:该项值用来表示是哪家的搜索引擎
    • ‘allow’:允许被爬取的url
    • ‘disallow’:不允许被爬取的url
  • 5.3 搜索引擎返回的都是网页,并且返回90%的都是无用的数据
  • 5.4 不能够根据不同的用户需求或者检索结果返回不同的结果

第6章 OSI七层协议:

从上往下:
应用层:为用户的应用程序提供网络服务的(http,https,ftp。。。。。)
表示层:负责端到端的数据信息可以被另一个主机所理解和识别,并且按照一定的格式将信息传递到会话层
会话层:管理主机之间的会话进程,负责建立,管理,和终止会话进程
传输层:进行数据传输(TCP UDP)
网络层: 路由器
数据链路层:网桥 交换机
物理层 : 网线 网卡 集线器 中继器

第7章 常见的请求状态码:

200 :请求成功

301 : 永久重定向
302 : 临时重定向

401 : 未授权
403 : 服务器拒绝访问
404 : 页面丢失
405 : 请求方式不对
408 : 请求超时

500 : 服务器错误
503 : 服务器不可用

第8章 发起请求:

会携带请求头

  • ’USer-Agent‘:模拟浏览器请求
  • ‘Cookies’:存储在浏览器里,使用cookie表明身份
  • ‘Refere’:说明当前请求是从哪个页面发起

第9章 使用urllib发起请求:

#目标url
url = 'http://www.baidu.com/'

# request.urlopen():使用urlopen方法模拟浏览器发起请求
"""
url, 请求的目标url地址
data=None,默认情况为None,表示发起的是一个get请求,不为None,则发起的是一个post请求
timeout=,设置请求的超时时间 
cafile=None, 设置证书
capath=None, 设置证书路径
cadefault=False, 是否要使用默认证书(默认为False)
context=None:是一个ssl值,表示忽略ssl认证
"""

#是一个ssl值,表示忽略ssl认证(如果请求出现了ssl证书认证错误,
# 我们就需要设置ssl._create_unverified_context(),忽略证书认证)
content = ssl._create_unverified_context()
response = request.urlopen(url,timeout=10,content=content)
#从response响应结果中获取参数
#状态码
code = response.status
print(code)
#获取页面源码的二进制数据
b_html = response.read()
print(type(b_html),len(b_html))
#获取响应的响应头部(Response Headers)
res_headers = response.getheaders()
print(res_headers)
#获取响应头中指定参数的值
cookie_data = response.getheader('Set-Cookie')
print(cookie_data)
#reason返回一个响应结果的原因
reason = response.reason
print(reason)

#将获取到的二进制数据,转换为字符串decode
str_html = b_html.decode('utf-8')
print(type(str_html))

with open('b_baidu.page.html','w') as file:
    # file.write(b_html)
    file.write(str_html)


#如果请求要携带请求头

#需要先构建一个request对象
"""
url:发起请求的url地址
data=None, 默认情况为None,表示发起的是一个get请求,不为None,则发起的是一个post请求
headers={},设置请求头(headers对应的数据类型是一个字典)
origin_req_host=None, (指定发起请求的域)
unverifiable=False,忽略SSL认证
method=None:指定发起请求的方式
"""
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
req = request.Request(url,headers=req_header)

#根据构建的req请求对象发起请求
response = request.urlopen(req)
response.status

第10章 正则表达式:

. :表示匹配除了换行符之外的任意字符
\ :转义字符
[a-z] : 匹配a-z里面的任意一个字符
's'     匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'

\d: 匹配数字 -> [0-9]
\D: 匹配非数字 [^\d]
\s: 匹配空白字符(空格,\n,\t...)
\S: 匹配非空白字符 
\w: 匹配单词字符 [A-Za-z0-9_]
\W: 匹配非单子字符


^:匹配以...开头
$:匹配以....结尾

():分组
|:'|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
'(?P...)' 分组匹配 re.search("(?P[0-9]{4})(?P[0-9]{2})(?P[0-9]{4})",
"371481199306143242").groupdict("city")
结果{'province': '3714', 'city': '81', 'birthday': '1993'}

多字符匹配
*:匹配*前面的字符任意次数
+ : 匹配+号前面的字符至少1次
?: 匹配?前面的字符0次或1{m}:匹配{m}前面的字符m次
{m,n}:匹配{m,n}前面的字符m~n次

非贪婪匹配
*?
+?
??
{m,n}?

原字符
r : 原来的字符串怎么写,现在就怎么写
例如 url(r'^admin/', admin.site.urls)

第11章 列子(re模块是python中处理正则表达式的一个模块)

import re

#把正则表达式构建为一个pattern对象
sub_str = 'abcdefabcd'
pattern = re.compile('b')
#从字符串的起始位置开始匹配,开头就必须符合正则规则,
# 如果匹配到结果了返回结果,如果匹配不到返回None,单次匹配
result = re.match(pattern,sub_str)
print(type(result))
if result:
    print(result.group())

#在整个字符串中进行匹配,同样是单次匹配,匹配到结果立即返回
#匹配不到则返回None
result = re.search(pattern,sub_str)
print(result.group())

# 再整个字符串中进行匹配,匹配出所有符合正则规则的结果,
# 以列表的形式返回
result = re.findall(pattern,sub_str)
print(result)

#再整个字符串中进行匹配,匹配出所有符合正则规则的结果,
#但是返回的是一个迭代器
result = re.finditer(pattern,sub_str)
# 
print(type(result))
for note in result:
    #
    print(type(note))
    print(note.group())
#替换re.sub()
url = 'http://www.baidu.com/s?kw=aaa&pn=20'
# pattern, \正则规则
# repl, \要替换的字符串
# string,原始字符串
pattern = re.compile('pn=\d+')
result = re.sub(pattern,'pn=30',url)
print(result)

#分割re.split()
pattern = re.compile('[=:&]')
#pattern, string
result = re.split(pattern,url)
print(result)

sub_html = """

"""
#re.S让点可以匹配包括换行符的任意字符
pattern = re.compile(
    ''+
    '.*?',re.S
)

result = re.findall(pattern,sub_html)
print(result)

第12章 cookies的使用

from urllib import request
# 目标url:
# https://www.douban.com/people/175417123/

url = 'https://www.douban.com/people/175417123/'

# 设置请求头
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
    'Cookie': 'bid=a5HEJxBlOLY; douban-fav-remind=1; ll="108288"; _vwo_uuid_v2=D4EC41D965B5FF84E814BF48AE34386A5|f6047e628a6acc98722e3100dfbc399c; __yadk_uid=KpfeK1cgib5IWMKWvG66MnJMbonYvDZa; _ga=GA1.2.36315712.1531837787; douban-profile-remind=1; push_doumail_num=0; push_noty_num=0; __utmv=30149280.17541; _gid=GA1.2.2070226630.1545227516; ps=y; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1545292749%2C%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DqpgHwc2FYGfOrGzt4yK3ZwwbraVm_oED80whnivpFaC3kA5IvGnUfQ9FSRZBOEVh%26wd%3D%26eqid%3D85ed620e000397aa000000065c1b4bc8%22%5D; _pk_ses.100001.8cb4=*; __utma=30149280.36315712.1531837787.1545227511.1545292752.48; __utmc=30149280; __utmz=30149280.1545292752.48.37.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utmt=1; dbcl2="175417123:yY3DyEelGJE"; ck=FxtM; ap_v=0,6.0; _pk_id.100001.8cb4=7521abce5497fc2c.1531837784.39.1545292778.1545228853.; __utmb=30149280.7.10.1545292752',
}

req = request.Request(url=url,headers=req_header)

response = request.urlopen(req)

if response.status == 200:
    with open('douban.html','w') as file:
        file.write(response.read().decode('utf-8'))

第13章 cookiejar的使用

#使用cookiejar的目的:管理cookie,保存cookie值,
#一旦存储cookie之后,下一次发起请求的时候就会携带cookie
#cookie是保存在内存里面的,最后会进行垃圾回收

from urllib import request,parse
from http.cookiejar import CookieJar

#创建cookiejar对象,目的如上
cookie_jar = CookieJar()

#HTTPCookieProcessor创建handle处理器,管理cookiejar
handler = request.HTTPCookieProcessor(cookie_jar)

#自定义opener
opener = request.build_opener(handler)

#分析发现
# https://www.douban.com/accounts/login
# 没有验证码的情况
# source: index_nav
# form_email: 18518753265
# form_password: ljh12345678

#有验证码的情况
# source: index_nav
# form_email: 18518753265
# form_password: ljh12345678
# captcha-solution: blade
# captcha-id: 5IBtw5wm2riyrIrnV3utwUPt:en

url = 'https://www.douban.com/accounts/login'

form_data = {
    'source': 'index_nav',
    'form_email': '18518753265',
    'form_password': 'ljh12345678',
    'captcha-solution': 'noise',
    'captcha-id': 'waNQIJD6TkMaF4M51PFg5kYh:en'
}

form_data = parse.urlencode(form_data).encode('utf-8')

#设置请求头
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}

#够建一个request对象
req = request.Request(url,headers=req_header,data=form_data)

#发起请求
response = opener.open(req)

#登录成功后访问个人主页,能够成功获取到个人主页信息,说明确实保存了cookie
#并且在一下次发起请求的时候携带了cookie
url = 'https://www.douban.com/people/175417123/'

req = request.Request(url,headers=req_header)

response = opener.open(req)

if response.status == 200:
    with open('douban.html','w') as file:
        file.write(response.read().decode('utf-8'))

第14章 urllib.error的使用

# urllib.error:在发起请求的过程中,可能会因为各种情况
# 导致请求出现异常,因而导致代码崩溃,所以我们悬疑处理这些异常的请求

from urllib import error,request

# error.URLError

def check_urlerror():
    """
    1.没有网络
    2.服务器连接失败
    3.找不到指定服务器
    :return:
    """
    url = 'http://www.baidu.com/'
    try:
        response = request.urlopen(url,timeout=0.01)
        print(response.status)
    except error.URLError as err:
        #[Errno -2] Name or service not known(未知服务器)
        #timed out:请求超时
        #[Errno -3] Temporary failure in name resolution(没网)
        print(err.reason)

# check_urlerror()

# error.HTTPError是URLError的子类

def check_httperror():
    url = 'https://www.qidian.com/all/nsacnscn.htm'
    try:
        response = request.urlopen(url)
        print(response.status)
    except error.HTTPError as err:
        #HTTPError的三个属性
        #状态码
        print(err.code)
        #返回错误的原因
        print(err.reason)
        #返回响应头
        print(err.headers)
    except error.URLError as err:
        print(err.reason)

check_httperror()

第15章 urllib的parse模块的使用

#urllib的parse模块主要是实现url的解析,合并,编码,解码

from urllib import  parse

#parse.urlparse实现了url的识别和分段
url = 'https://www.1712B.com/daxuesheng?name=zhangsan#123'
"""
url,:要解析和才分的url
scheme='':设置协议,只有在url没有协议的情况下才会生效
allow_fragments=True:是否忽略锚点,默认为True表示不忽略
"""
result = parse.urlparse(url)
"""
(scheme='https'(协议), netloc='www.1712B.com'(域), 
path='/daxuesheng'(路径), params=''(可选参数), 
query='name=zhangsan'(查询参数), fragment='123'(锚点))
"""
print(result)
#取出才分后的某一个参数
print(result.scheme)

#parse.urlunparse可以实现url的组合
data = [sub_str for sub_str in result]
print('-----',data)
full_url = parse.urlunparse(data)
print(full_url)

#parse.uurlrljoin需要传递一个基类url,根据基类将某一个不完整的url拼接完整
sub_url = '/p/123456'
base_url = 'https://www.1712B.com/daxuesheng?name=zhangsan#123'
full_url = parse.urljoin(base_url,sub_url)
print('urljoin',full_url)

#parse.urlencode将字典类型的参数,序列化为url的编码格式的字符串
parmars = {
    'name':'张三',
    'class':'1712B',
}
result = parse.urlencode(parmars)
print('urlencode',result)

#parse.parse_qs反序列化,将url编码格式的字符串,转为字典类型
result = parse.parse_qs(result)
print('parse_qs',result)

#parse.quote可以将中文字符,转为url编码格式
kw = '摸摸摸'
result = parse.quote(kw)
print('quote',result)

#将url编码进行解码
result = parse.unquote(result)
print('unquote',result)


# 最最常用的urljoin,urlencode两个方法

第16章 urllib_proxy的使用

# urllib下使用代理
# http/https代理
# 一定是一个高匿代理理
# 隐藏真实ip

from urllib import request

#自定义ProxyHandler的目的是为了设置代理,使用代理发起请求
#proxies:对应的是一个字典
# 代理有免费代理(西刺,快代理.....)
# 和收费代理 (西刺,快代理.....,阿布云....)
# proxies = {
#     'http':'118.187.58.34:53281',
#     'https':'124.235.180.121:80',
# }

#独享代理,需要账号密码做验证的
proxies = {
    'http':'http://2295808193:[email protected]:16818',
    'https':'https://2295808193:[email protected]:16818'
}
handler = request.ProxyHandler(proxies=proxies)

#自定义opener
opener = request.build_opener(handler)

#url地址
#https://httpbin.org/get
url = 'http://httpbin.org/get'

response = opener.open(url)

print(response.status)
print(response.read().decode('utf-8'))

第17章 requests模块

#pip3 install requests
#requests模块:是对urllib的封装,可以实现urllib的所有功能
#并且api调用更加简单方便

import requests

# url = 'http://www.baidu.com/'
url = 'http://www.sina.com'
# url, :要请求的目标url
# params:get请求后面要拼接的参数
"""
:param method: 要发起的是什么类型的请求.
:param url: 要请求的目标url
:param params: get请求后面要拼接的参数
:param data: Dictionary, post请求的表单数据
:param json: 传递json数据跟上面的data效果类似
:param headers: (optional) Dictionary 请求头
:param cookies: (optional) Dict or CookieJar object (设置cookies信息模拟用户请求)
:param files: 上传文件
:param auth: 网站需要验证的信息(账号和密码)
:param timeout: 设置请求的超时时间
:param allow_redirects: bool,是否允许重定向
:param proxies: (optional) Dictionary (设置代理)
:param verify:  Defaults to ``True``.(忽略证书认证,默认为True表示不忽略)
"""
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}
parmars = {
    'wd':'豆瓣'
}
# response = requests.get(url,params=parmars,headers=req_header)
response = requests.get(url,headers=req_header)
response.encoding='utf-8'

#从响应结果中获取的信息
#(这里得到的是解码后的字符串)
html = response.text

"""
#如果使用response.text出现了乱码
方式一
#response.content.decode('')
方式二
response.encoding=''设置编码类型
"""

#获取bytes类型的数据
b_html = response.content
#获取状态码
code = response.status_code
#获取响应头
response_headers = response.headers
#请求头
req_headers = response.request.headers
#获取当前请求的url地址
current_url = response.url
#response.json():可以将json字符串转为python数据类型
print(code)
print(html)

第18章 resquests_post请求

import requests

#url, 目标url
# data=None,:post请求要上传的表单数据

url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'

form_data = {
    'first': 'true',
    'pn': 1,
    'kd': 'python',
}

#设置请求头
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
    'Referer': 'https://www.lagou.com/jobs/list_python?city=%E5%85%A8%E5%9B%BD&cl=false&fromSearch=true&labelWords=&suginput=',
}

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

print(response.status_code)

print(response.text)

#可以吧将返回的json字符串转为python数据类型
data = response.json()
print(type(data))

第19章 requests_outh

#web客户端验证
import requests

#设置认证信息
auth = ('username','password')

url = 'http://192.168.1.110'

response = requests.get(url,auth=auth)

print(response.status_code)

第20章 requests下使用cookies

import requests
#分析发现
# https://www.douban.com/accounts/login
# 没有验证码的情况
# source: index_nav
# form_email: 18518753265
# form_password: ljh12345678

#有验证码的情况
# source: index_nav
# form_email: 18518753265
# form_password: ljh12345678
# captcha-solution: blade
# captcha-id: 5IBtw5wm2riyrIrnV3utwUPt:en

url = 'https://www.douban.com/accounts/login'

form_data = {
    'source': 'index_nav',
    'form_email': '18518753265',
    'form_password': 'ljh12345678',
    'captcha-solution': 'violent',
    'captcha-id': 'AuKNJ1FIktyrmpljJ6WAzXo3:en'
}

#设置请求头
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}

#发起请求
response = requests.post(url,headers=req_header,data=form_data)

#使用response.cookies获取cookies信息
print('模拟登录后的cookies信息',response.cookies)
print(type(response.cookies))
print(response.headers)

with open('douban.html','w') as file:
    file.write(response.text)

#requests.utils.cookiejar_from_dict():将字典转为cookiejar
#requests.utils.dict_from_cookiejar():将cookiejar转为字典
cookies_dict = requests.utils.dict_from_cookiejar(response.cookies)
print(cookies_dict)
#登录成功后访问个人主页,能够成功获取到个人主页信息,说明确实保存了cookie
#并且在一下次发起请求的时候携带了cookie
url = 'https://www.douban.com/people/175417123/'
#设置cookies参数,模拟用户发起请求
response = requests.get(url,headers=req_header,cookies=cookies_dict)

if response.status_code == 200:

    with open('douban1.html','w') as file:

        file.write(response.text)

第21章 使用requests模块设置代理

import requests

proxies = {
    'http':'219.238.186.188:8118',
    'https':'222.76.204.110:808',
    'https':'https://username:password@ip:port',
    'http':'http://username:password@ip:port'
}

url = 'https://httpbin.org/get'

response = requests.get(url,proxies=proxies,timeout=10)

print(response.text)

第22章 requests.session的使用

#requests.session():维持会话,可以让我们在跨请求时保存某些参数


import requests

#实例化session
session = requests.session()

#目标url
url = 'https://www.douban.com/accounts/login'

form_data = {
    'source': 'index_nav',
    'form_email': '18518753265',
    'form_password': 'ljh12345678',
    'captcha-solution': 'stamp',
    'captcha-id': 'b3dssX515MsmNaklBX8uh5Ab:en'
}

#设置请求头
req_header = {
    'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
}

#使用session发起请求
response = session.post(url,headers=req_header,data=form_data)

if response.status_code == 200:

    #访问个人主页:
    url = 'https://www.douban.com/people/175417123/'

    response = session.get(url,headers = req_header)

    if response.status_code == 200:

        with open('douban3.html','w') as file:

            file.write(response.text)

第23章 xpath的使用

  • xpath:可以在xml中查找信息,对xml文档中元素进行遍历和属性的提取

  • xml:被设计的目的是为了传输数据,结构和html非常相识,是一种标记语言

第24章 xpath常见的语法:

nodename 选取此节点的所有子节点
/        从根节点开始查找
//       匹配节点,不考虑节点的位置
.        选取当前节点
..       选取当前节点的父节点
a/@href        取标签的数据
a/text()       取标签的文本
a[@class="123"] 根据class属性寻找标签
a[@id="123"]    根据id属性寻找标签

a[@id="123"][last()]  取最后一个id123的a标签
a[@id="123"][postion() < 2]id123的前两个a标签

参考简书:https://www.jianshu.com/p/70d064d843e6

你可能感兴趣的:(爬虫)