Python网络爬虫与信息提取


title: Python网络爬虫与信息提取 date: 2020-12-10 01:00:23 tags: Python categories: 学习笔记


写在前面 不知道写啥其实说实话

[TOC]

网络爬虫之规则

安装requests库

cmd 命令行打开

输入pip3 install requests,等待即可

简单测试,爬一下bkjw

import requests r = requests.get("http://172.16.13.22/") print(r.status_code) r.encoding = 'utf-8' print(r.text) 200 <script type="text/javascript"> if (location.href.toLowerCase().lastIndexOf('maindesktop', 0) > 0) top.location.href = "/"; </script> <link rel="stylesheet" type="text/css" href="/extjs/resources/css/ext-all-gray.css" /> <!--引入自定义CSS--> <link href="/Content/css/iconCss.css" rel="stylesheet" type="text/css" /> <link href="/extjs/Desktop/css/desktop.css" rel="stylesheet" type="text/css" /> <link rel="stylesheet" type="text/css" href="/Content/style.css" /> <script type="text/javascript" src="/extjs/ext-all.js"></script> <script type="text/javascript" src="/extjs/locale/ext-lang-zh_CN.js"></script> <script src="/extjs/Extensions/CustomValidate.js" type="text/javascript"></script> <script src="/extjs/Extensions/Util.js?v=0.1" type="text/javascript"></script> <script src="/extjs/Desktop/login.js?v=0.1" type="text/javascript"></script>

requests库7个主要方法

方法说明
requests.request()构造一个请求,支撑以下各方法的基础方法
requests.post()向网页提交post请求
requests.head()获取网页头信息
requests.put()向网页提交put请求
requests.patch()向网页提交局部修改请求
requests.delete()向网页提交删除请求
requests.get()向网页提交get请求

requests库其实只有一个方法——request()方法,其他六种方法都是对request()方法的封装

requests库异常处理

异常说明
requests.ConnectionError网络连接错误异常,如DNS查询失败、拒绝连接
requests.HTTPErrorHTTP错误异常
requests.URLRequiredURL缺失
requests.TooManyRedirects超过最大重定向次数,产生重定向异常
requests.ConnectTimeout连接远程服务器超时异常
requests.Timeout请求URL超时,产生超时异常

response对象的常用属性和方法

**dir()**一个response对象可以看到它的属性和方法

['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']

常用的属性

属性说明
r.headersHTTP响应头
r.status_codeHTTP请求的返回状态,200表示连接成功,404表示失败
r.textHTTP响应内容的字符串形式,即url对应的页面内容
r.encoding从HTTP header中猜测的响应内容编码方式
r.apparent_encoding从内容中分析出的响应内容编码方式(备选编码方式)
r.contentHTTP响应内容的二进制形式
r.okHTTP请求成功没,返回True或False

r.encoding:如果 header 中不存在 charset,则认为编码为ISO-8859-1,不太准确

r.apparent_encoding:备选编码,从网页的内容分析编码方式,一般准确

常用 r.encodint = r.apparent_encoding

通用代码框架

# -*- coding: utf-8 -*- """ @Time : 2020/12/10 @Author : C1everF0x @File : demo.py @Description : """ import requests def getHTMLText(url): try: r = requests.get(url,timeout=30) r.raise_for_status() #判断异常 r.encoding = r.apparent_encoding return r.text except: return "产生异常" if __name__== "__main__": url = "https://search.bilibili.com/all?keyword=%E5%AE%AB%E6%9C%AC%E7%8B%97%E9%9B%A8" print(getHTMLText(url))

Requests库方法详解

重中之重:requests.request()

原型:requests.request(method,url,**kwargs)

  • method:对应http协议中的七种请求方法
  • url:请求的链接
  • **kwargs:控制访问的参数,共13个

requests.get()

原型:requests.get(url,params=None,**kwargs)

  • url:请求的链接
  • params:url中的额外参数,字典或字节流格式,可选
  • **kwargs:控制访问的参数
# 传参方法一,直接在url里面拼接 url = ”https://search.bilibili.com/all?keyword=宫本狗雨“ r = requests.get(url) print(r.url) # 传参方法二,将参数保存为字典,传给 params url = "https://search.bilibili.com" params = { "all?keyword":"宫本狗雨" } r = requests.get(url.params=params) print(r.url)

requests.post()

原型:requests.post(url,data=None,json=None,**kwargs)

  • url:请求的链接
  • data:请求的内容,可以是字典,字节序列或文件
  • json:JSON 格式数据,也是请求的内容
  • **kwargs:控制访问的参数
# 传参方法一:直接post字典 url = “https://www.baidu.com” payload = {"key":"valus"} r = requests.post('url',data = payload) printf(r.text) # 传参方法二:data = 字符串 url = “https://www.baidu.com” r = requests.post('url',data = ‘ABCDEFG’) printf(r.text)

data 等于一个字典的时候,用户传输的数据会被编码到 form 表单当中

而 data 直接等于一个字符串的时候,用户传输的数据会被编码到 data 里面

13个访问控制参数

**kwargs:控制访问的参数

  • params:字典或者字节序列,作为参数增加到 url
  • data:字典、字节序列或文件对象,作为 request 的内容
  • json: JSON 格式的数据,作为 request 的内容
  • headers:字典,HTTP定制头
  • cookies:字典或者 cookiejar,作为 request中的 cookie
  • auth:元组,支持HTTP认证功能
  • files:字典类型,传输文件
  • timeout:设定超时时间,秒为单位,超时返回异常
  • proxies:字典类型,设定访问代理服务器的 ip 地址,可以增加登陆认证
  • allow_redirects:True/False,默认为True,重定向开关
  • stream:True/False,默认为True,获取内容立即下载开关
  • verify:True/False,默认为True,认证 SSL 证书开关
  • cert:本地 SSL 证书路径

爬虫规则

爬网页爬网站、系列网站爬全网
小规模中规模大规模
爬取速度不敏感爬取速度敏感爬取速度关键
Requests库Scrapy库定制库

不要乱爬,乱爬容易出事,不然哪天就进去了

Robots协议

  • 网站告知爬虫哪些页面可以爬,哪些不能爬,遵不遵守看个人
  • 如果网站根目录下没有robots.txt,则表示该网站所有东西都可以爬
  • 类人行为可不参考Robots协议,因为其不会对服务器产生很大的影响,,但是获取的东西不能用于商业用途

网络爬虫之提取

BeautifulSoup库

  • 一般引用 bs4 库中的BeautifulSoup类就够了
from bs4 import BeautifulSoup soup = BeautifulSoup("<p>python</p>","html.parser")

基本元素

  • 标签树就是汤,BeautifulSoup类就是将一个标签树变成一个变量,用类里面的方法来熬汤(解析标签树)
基本元素解释
Tag标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾
Name标签的名字,<p>…</p>的名字是'p',格式:<tag>.name
Attributes标签的属性,字典形式组织,格式:<tag>.attrs
NavigableString标签内非属性字符串,<>…</>中字符串,格式:<tag>string
Comment标签内字符串的注释部分,一种特殊的Comment类型

如何判断解析出来的字符串是注释还是非属性字符串?

type来判断,BeautifulSoup类中这两个的类型不一样

解析器

  • 一共支持四种解析器
  • 其中xmllxml需要额外安装lxml库,html5lib需要额外安装html5lib
解析器使用方法依赖
bs4的HTML解析器BeautifulSoup(mk,'html.parser')安装bs4库
lxml的HTML解析器BeautifulSoup(mk,'lxml')pip install lxml
xml的XML解析器BeautifulSoup(mk,'xml')pip install lxml
html5lib的解析器BeautifulSoup(mk,'html5lib')pip install html5lib

基于bs4库的HTML的内容遍历方法

上行遍历

属性说明
.parent节点的父亲标签
.parents节点先辈标签的迭代类型,用于循环遍历先辈节点
for parent in soup.a.parents: if parent is None: print(parent) else: print(parent.name) p body html [document]

下行遍历

属性说明
.contents子节点的列表,将<tag>的所有儿子节点存入列表
.children子节点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants子孙节点的迭代类型,包含所有子孙节点,用于循环遍历
for child in soup.body.children: print(child) <p class="title"><b>The demo python introduces several python courses.</b></p> <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses: <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p> for child in soup.body.descendants: print(child) <p class="title"><b>The demo python introduces several python courses.</b></p> <b>The demo python introduces several python courses.</b> The demo python introduces several python courses. <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses: <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p> Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses: <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> Basic Python and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a> Advanced Python .

平行遍历

属性说明
.next_sibling返回按照HTML文本顺序的下一个平行节点标签
.previous_sibling返回按照HTML文本顺序的上一个平行节点标签
.next_siblings迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_siblings迭代类型,返回按照HTML文本顺序的前续所有平行节点标签
soup.a <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> soup.a.next_sibling ' and ' soup.a.next_sibling.next_sibling <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
for sibling in soup.a.next_siblings: print(sibling) and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a> . for sibling in soup.a.previous_siblings: print(sibling) Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:

节点

  • 结点不仅仅是尖括号 <> 的标签,还有一些字符内容,比如\n或标签中未被包裹的字符串,都是节点

美化与编码

  • prettify()方法用于美化标签内容排版,其实就是加\n来换行,让标签树显示更加美观
  • BeautifulSoup库对所有传入的HTML文档和字符串都解析成UTF-8编码,Python3 默认也是UTF-8编码,Python2 不是

信息组织与提取

网络爬虫之实战

Re 库入门

正则表达式语法

  • 正则表达式语法由字符和操作符组成
操作符说明实例
.表示任何单个字符.* 表示任意字符
[]字符集,对单个字符给出取值范围[abc] 表示a、b、c,[a-z] 表示a到z单个字符
[^]非字符集,对单个字符给出排除范围[^abc] 表示非a、b、c的单个字符
*前一个字符0次或无限次扩展abc* 表示ab、abc、abcc、abccc等
+前一个字符1次或无限次扩展abc+ 表示abc、abcc、abccc等
?前一个字符0次或1次扩展abc? 表示ab、abc
``左右表达式任意一个
{m}扩展前一个字符m次**ab{2}c **表示abbc
{m,n}扩展前一个字符m至n次(含n)**ab{1,2}c **表示abc、abbc
^匹配字符串开头**^abc **表示abc且在一个字符串的开头
$匹配字符串结尾**abc$ **表示abc且在一个字符串的结尾
()分组标记,内部只能使用| 操作符(abc) 表示abc,(abc|def)表示abc、def
\d数字,等价于[0‐9]
\w单词字符,等价于[A‐Za‐z0‐9_]
  • 经典举例
re说明
^[A-Za-z]+$由26个字母组成的字符串
^[A-Za-z0-9]+$由26个字母和数字组成的字符串
^-?\d+$整数形式的字符串
^[0-9]*[1-9][0-9]*$正整数形式的字符串
[1-9]\d{5}中国境内邮政编码,6位
[\u4ee00-\u9fa5]匹配中文字符,用utf-8编码中中文字符的区间代替
`\d{3}-\d{8}\d{4}-\d{7}`
  • 非常经典的匹配 IP 地址的正则表达式

0-99[1-9]?\d

100-1991\d{2}

200-2492[0-4]\d

250-25525[0-5]

整合:(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])

re 库基本使用

  • python 的标准库,不需要额外安装
  • raw string 原生字符串类型
    • re 库采用原生字符串类型来表示正则表达式,形如 r'text',用 string 类型也行,但是要用转义字符来转义反斜杠,会更麻烦
    • 比如:r'[1-9]\d{5}'r'\d{3}-\d{8}|\d{4}-\d{7}'
    • **raw string **是不包含转义符的字符串,转义符比如反斜杠\
  • re 库常用功能函数
函数说明
re.search()在一个字符串中搜索匹配正则表达式的第一个位置,返回 match 对象
re.match()从一个字符串的开始位置起匹配正则表达式,返回 match 对象
re.findall()搜索字符串,以列表类型返回全部能匹配到的子串
re.split()将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
re.finditer()搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是 match 对象
re.sub()在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串

re.search(pattern,string,flags=0)

  • 在一个字符串中搜索匹配正则表达式的第一个位置,返回 match 对象

    • pattern:正则表达式的字符串或原生字符串表示

    • string:待匹配字符串

    • flags:正则表达式使用时的控制标记

      常用标记说明
      re.I re.IGNORECASE忽略正则表达式的大小写,[A-Z]能够匹配大小写
      re.M re.MULTILINE正则表达式中的^操作符能够将给定字符串的每行当作匹配开始
      re.S re.DOTALL正则表达式中的.操作符能够匹配所有字符,默认匹配是除换行以外的所有字符
>>> import re >>> match = re.search(r'[1-9]\d{5}', 'BIT100081') >>> if match: print(match.group(0)) 100081

re.match(pattern,string,flags=0)

  • ==从一个字符串的开始位置起==匹配正则表达式,返回 match 对象
    • pattern:正则表达式的字符串或原生字符串表示
    • string:待匹配字符串
    • flags:正则表达式使用时的控制标记
>>> match = re.match(r'[1-9]\d{5}', 'BIT 100081')>>> if match: match.group(0) #无输出>>> match.group(0)#直接调用报错,说明没有匹配到Traceback (most recent call last): File "<pyshell#9>", line 1, in <module> match.group(0)AttributeError: 'NoneType' object has no attribute 'group'>>> match = re.match(r'[1-9]\d{5}', '100081 BIT')>>> if match: match.group(0) '100081'

re.findall(pattern,string,flags=0)

  • 搜索字符串,以列表类型返回全部能匹配的子串
    • pattern:正则表达式的字符串或原生字符串表示
    • string:待匹配字符串
    • flags:正则表达式使用时的控制标记
>>> ls = re.findall(r'[1-9]\d{5}', 'BIT100081 TSU100084')>>> ls['100081', '100084']

re.split(pattern,string,maxsplit=0,flags=0)

  • 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型,也就是将匹配到的字符串去掉,剩下的存进列表返回
    • pattern:正则表达式的字符串或原生字符串表示
    • string:待匹配字符串
    • maxsplit:最大分割数,剩余部分作为最后一个元素输出
    • flags:正则表达式使用时的控制标记
>>> re.split(r'[1-9]\d{5}', 'BIT100081 TSU100084') ['BIT', ' TSU', ''] >>> re.split(r'[1-9]\d{5}', 'BIT100081 TSU100084', maxsplit=1) ['BIT', ' TSU100084']

re.finditer(pattern,string,flags=0)

  • 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
    • pattern:正则表达式的字符串或原生字符串表示
    • string:待匹配字符串
    • flags:正则表达式使用时的控制标记
>>> for m in re.finditer(r'[1-9]\d{5}', 'BIT100081 TSU100084'): if m: print(m.group(0)) 100081 100084

re.sub(pattern,repl, string,count=0,flags=0)

  • 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
    • pattern:正则表达式的字符串或原生字符串表示
    • repl:替换匹配字符串的字符串
    • string:待匹配字符串
    • count:匹配的最大替换次数
    • flags:正则表达式使用时的控制标记
>>> re.sub(r'[1-9]\d{5}', ':zipcode', 'BIT100081 TSU100084')'BIT:zipcode TSU:zipcode'

两种用法

  • 函数式用法:一次性操作

    rst = re.search(r'[1-9]\d{5}','BIT 10091')

  • 面向对象用法:将原生字符串编译成一个 re 类的对象,能够进行多次操作

    pat = re.compile(r'[1-9]\d{5}')

    rst = pat.search('BIT 10091')

  • re.compile(pattern,flags=0)

    • 将正则表达式的字符串形式编译成正则表达式对象
    • pattern:正则表达式的字符串或原生字符串表示
    • flags:正则表达式使用时的控制标记

match 对象

  • match 对象的属性
属性说明
.string待匹配的文本
.re匹配时使用的pattern对象(正则表达式)
.pos正则表达式搜索文本的开始位置
.endpos正则表达式搜索文本的结束位置
  • match 对象的方法
方法说明
.group(0)获得匹配后的字符串
.start()匹配字符串在原始字符串的开始位置
.end()匹配字符串在原始字符串的结束位置
.span()返回(.strat(),.end())

re 库中贪婪匹配和最小匹配

  • re 库默认采用贪婪匹配,匹配最长的子串
>>> match = re.search(r'PY.*N', 'PYANBNCNDN') >>> match.group(0) 'PYANBNCNDN'
  • 通过在操作符后添加 ? 可变成最小匹配
操作符说明
*?前一个字符0次或无限次扩展,最小匹配
+?前一个字符1次或无限次扩展,最小匹配
??前一个字符0次或1次扩展,最小匹配
{m,n}?扩展前一个字符m至n次(含n),最小匹配

网络爬虫之框架

Scrapy爬虫框架

  • 安装
pip install scrapy
  • 框架结构(直接上图,思路很清晰)

最近没什么项目需求需要我用 Scrapy 框架来写,所以就没实践操作这个框架

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

Python3:sqlalchemy对mysql数据库操作,非sql语句

Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''

Java爬虫之JSoup使用教程

title:Java爬虫之JSoup使用教程date:201812248:00:000800update:201812248:00:000800author:mecover:https://imgblog.csdnimg.cn/20181224144920712(https://www.oschin