requests库
get函数:
get方法中的params参数以及12个可选参数跟request方法是相同的,往下看有解释
查看源码,可以发现get方法是通过调用request方法来实现的,其余5个方法也是通过调用request方法来实现的,实际上只使用request方法就可以了,其余6个方法是为了方便而产生的。
调用方法后返回的Response对象包含了网页的所有内容,常用的属性有:
返回的状态码表明的情况以及可以进行的操作:
r.encoding()方法是根据头信息中charset返回响应内容的编码,如果头信息中没有charset,则认为编码是ISO-8859-1
r.apprent_encoding()方法根据HTTP内容部分来分析响应内容可能的编码
requests库的异常:
调用requests库的方法返回的Response对象,也提供了一个跟异常相关的方法,该方法如果返回200则说明返回的内容没有异常,如果返回的内容有问题则会返回一个异常
request方法:
其中OPTIONS是用于获取服务器跟客户端打交道的一些参数
13个可选参数中的params,通过返回的response对象我们可以发现,该参数用于把一些键值对增加到url中,使得访问时带一些参数
data参数作为request的内容,可以使用POST方法将该数据存储到url指定位置
json参数跟data参数类似
headers参数,可以设置向某url连接访问时发起的http请求的头字段
cookies,从http协议中解析cookie
files参数用于向服务器传输文件
proxies参数,用于设置访问代理服务器,这样我们在访问url的时候使用的就是代理服务器的ip地址,使用该参数可以有效隐藏用户爬取网页的源ip地址信息,能够有效防止爬虫的反追踪
head方法,参数同request一样
post方法,11个可选参数也是除data跟json两个参数外,跟request方法一样
put、patch方法同上
HTTP协议
网络爬虫![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c31eb6a5f5e948685d17bcb5f13f9897.png)
网络爬虫的限制:
robots协议的基本语法,表明了那些是不可以爬取的内容,User-agent是一个标识,用于标识发起爬虫请求的程序
BeautifulSoup
Beautiful Soup库,能够对html、xml格式进行解析并且提取其中的相关信息
相关链接:https://www.crummy.com/software/BeautifulSoup/
BeautifulSoup库的引用,其中BeautifulSoup是一个类
BeautifulSoup类的使用:第一个参数是html代码,第二个参数是指定解析器
Beautiful库的解析器:一般使用html解析器就行了
BeautifulSoup类的基本元素
使用示例:
import requests
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
# print(soup.prettify())
print(soup.a.name)
# 有多个a标签时只会返回第一个
print(soup.a)
# a标签的父标签的名称
print(soup.a.parent.name)
tag = soup.a
# tag变量的类型是bs4库的标签类型
print(type(tag))
# attrs获得一个字典,返回标签的属性
print(tag.attrs)
print(type(tag.attrs))
print(tag.attrs['href'])
# 返回a标签中的内容,如果标签内还有标签,则可以跨越多个标签输出内容
print(tag.string)
print(type(tag.string))
newsoup = BeautifulSoup("<b><!-- This is a comment--></b><p>This is not a comment</p>","html.parser")
# 注释类型
print(type(newsoup.b.string))
print(type(newsoup.p.string))
# 输出注释的时候不会有标识
print(newsoup.b.string)
print(newsoup.p.string)
运行结果:
a
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
p
<class 'bs4.element.Tag'>
{'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1'], 'id': 'link1'}
<class 'dict'>
http://www.icourse163.org/course/BIT-268001
Basic Python
<class 'bs4.element.NavigableString'>
<class 'bs4.element.Comment'>
<class 'bs4.element.NavigableString'>
This is a comment
This is not a comment
基于bs4库的html内容遍历方法:
标签树的下行遍历:
对于一个标签的儿子节点,并不仅仅包括标签节点,也包括字符串节点,比如\n的回车也是body标签的儿子节点类型
import requests
from bs4 import BeautifulSoup
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
print(soup.head)
print(soup.head.contents)
print(soup.head.contents[0])
# 输出body标签的儿子节点,列表i形式
print(soup.body.contents)
# 输出body标签的儿子节点的个数
print(len(soup.body.contents))
print("-------------------")
# 遍历儿子节点
for child in soup.body.children:
print(child)
print("-------------------")
# 遍历子孙节点
for child in soup.body.descendants:
print(child)
运行结果:
<head><title>This is a python demo page</title></head>
[<title>This is a python demo page</title>]
<title>This is a python demo page</title>
['\n', <p class="title"><b>The demo python introduces several python courses.</b></p>, '\n', <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>, '\n']
5
-------------------
<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>
-------------------
<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
.
标签树的上行遍历:
这里要注意,在遍历soup的a标签的所有先辈标签的时候,会遍历到soup(soup本身也有特定的标签,但其没有父标签,所以输出其父标签结果为空)
标签树的平行遍历:
尽管树形结构采用标签来组织,但是标签中的NavigableString(内容)也构成了标签树的节点,任何一个节点的平行标签、父亲标签、儿子标签可能存在NavigableString类型,所以平行遍历获得的下一个节点一定是标签类型
import requests
from bs4 import BeautifulSoup
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
print("------平行遍历-----------")
print(soup.a.next_sibling)
print(soup.a.next_sibling.next_sibling)
print(soup.a.previous_sibling)
print(soup.a.previous_sibling.previous_sibling)
运行结果:
------平行遍历-----------
and
<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>
Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
None
基于bs4库的HTML格式输出:
使用prettify方法能够能html标签更加友好地显示:该方法能够对soup进行处理,也可以对每一个标签进行处理
import requests
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
print(soup.prettify())
print(soup.a.prettify())
运行结果:
<html>
<head>
<title>
This is a python demo page
</title>
</head>
<body>
<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>
</body>
a
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>
p
<class 'bs4.element.Tag'>
{'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1'], 'id': 'link1'}
<class 'dict'>
http://www.icourse163.org/course/BIT-268001
Basic Python
<class 'bs4.element.NavigableString'>
<class 'bs4.element.Comment'>
<class 'bs4.element.NavigableString'>
This is a comment
This is not a comment
PS D:\wampserver\www\code> & "e:/Program Files/Python36/python.exe" d:/wampserver/www/code/reptile/text5.py
<html>
<head>
<title>
This is a python demo page
</title>
</head>
<body>
<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>
</body>
</html>
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
Basic Python
</a>
信息提取:
基于bs4库的HTML内容查找方法:
BeautifulSoup提供了一个find_all方法,用于指定条件进行检索
import requests
from bs4 import BeautifulSoup
import re
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all('a'):
print(link.get('href'))
# 查找所有的a标签,返回一个列表
print(soup.find_all('a'))
# 查找所有的a和b标签,返回一个列表
print(soup.find_all(['a','b']))
# 如果给的name参数是True,将显示当前soup的所有标签信息
print(soup.find_all(True))
# 使用正则表达式库re输出所有以b开头的标签名
for tag in soup.find_all(re.compile('b')):
print(tag.name)
# 查找带有course属性值的p标签,返回一个列表
print(soup.find_all('p','course'))
# 查找id=link1的标签
print(soup.find_all(id='link1'))
# 使用正则表达式库re输出id为link开头的标签
print(soup.find_all(id=re.compile('link')))
# recursive参数置为False的话只对儿子节点进行检索
print(soup.find_all('a',recursive=False))
# 按标签内的字符串进行检索
print(soup.find_all(string="Basic Python"))
# 使用正则表达式库re对标签内字符串检索含有python的字符串域
print(soup.find_all(string = re.compile('python')))
正则表达式库re
转换后的正则表达式特征代表一组字符串
原生字符串类型和字符串类型的不同在于只需要再字符串类型前加上一个r,原生字符串不包含转义符,原生字符串内的\不被解释为转义符
正则表达式也可以用字符串类型表示,但是需要用两个\来表示正则表达式中的\,比较繁琐
使用re.M能够使正则表达式的^操作符匹配给定字符串的每一行
使用re.S能够使正则表达式中.操作符可以匹配任意字符
import re
match = re.search(r'[1-9]\d{5}','BIT 100081')
if match:
print(match.group(0))
import re
ls = re.split(r'[1-9]\d{5}','BIT100081 TSU100084')
print(ls)
输出结果为['BIT', ' TSU', '']
,可以发现split方法是将正则表达式匹配的内容去掉,然后将剩下的部分进行分割
import re
for m in re.finditer(r'[1-9]\d{5}','BIT100081 TSU100084'):
if m:
print(m.group(0))
结果:
100081
100084
import re
s = re.sub(r'[1-9]\d{5}','zipcode','BIT100081 TSU100084')
print(s)
如果需要多次对正则表达式进行匹配使用的话,可以使用以下的面向对象用法
正则表达式对象的方法,使用跟前面的是一样的,不过要去掉pattern,flags参数,因为在编译形成正则表达式对象的时候就已经使用了这两个参数
re库的match对象
import re
m = re.search(r'[1-9]\d{5}','BIT100081 TSU100084')
print(m.string)
print(m.re)
print(m.pos)
print(m.endpos)
print(m.group(0))
print(m.start())
print(m.end())
print(m.span())
结果:
BIT100081 TSU100084
re.compile('[1-9]\\d{5}')
0
19
100081
3
9
(3, 9)
re库的贪婪匹配和最小匹配
scrapy爬虫框架
Scrapy爬虫框架总共有5个模块,SPIDERS,ENGINE,SCHEDULER,DOWNLOADER,ITEM PIPELINES以及两个中间件模块
Scrapy框架包含3条主要的数据流路径:
- SPIDERS-1-ENGINE-2-SCHEDULER,SCHDULER模块主要负责对请求进行调度
- SCHEDULER-3-ENGINE-4-DOWNLOADER-5-ENGINE-6-SPIDERS
- SPIDERS-7-ENGINE-8-ITEM PIPELINES+SCHEDULER,ITEMS是爬取项,REQUESTS是新的爬取请求
使用Scrapy框架需要用户自己编写SPIDERS模块和ITEM PIPELINES模块,其中SPIDERS模块提供要访问的url链接,同时要解析从网络伤获得的页面的内容,而ITEM PIPELINES模块对提取的信息进行后处理
ENGINE的作用:
- 控制所有模块之间的数据流
- 根据条件触发事件
DOWNLOADER的作用:
- 根据请求下载网页
SCHDULER的作用:
- 对所有爬取请求进行调度管理
DOWNLOADER中间件的作用:可以对请求或响应进行配置
SPIDER的作用:
- 解析DOWNLOADER返回的响应
- 能够产生爬取项
- 产生额外的爬取请求
ITEM PIPELINES的作用:
- 以流水线方式处理SPIDER产生的爬取项
- 由一组操作顺序组成,类似流水线,每个操作是一个ITEM PIPELINE类型
- 可能操作包括:清理、检验和查重爬取项中的HTML数据、将数据存储到数据库
SPIDER中间件的作用:
scrapy是为持续运行设计的专业爬虫框架,提供了scrapy命令行,在windows系统下命令行使用命令scrapy -h就可以看到scrapy命令行
scrapy框架下,一个工程是一个最大的单元,一个工程相当于一个大的scrapy框架,在scrapy框架中可以有多个爬虫,每一个爬虫相当于一个SPIDER模块
在命令行下使用scrapy startproject python123demo命令,会在当前目录下产生一个python123demo文件夹,文件夹下的内容有:
切换到python123demo文件夹所在位置,使用命令scrapy genspider demo python123.io,生成一个名为demo的爬虫,爬取的网站域名为python123.io,在spiders目录下就会产生一个demo.py文件
对demo.py进行配置
import scrapy
class DemoSpider(scrapy.Spider):
name = 'demo'
allowed_domains = ['python123.io']
start_urls = ['http://python123.io/ws/demo.html']
def parse(self, response):
fname = response.url.split('/')[-1]
with open(fname,'wb') as f:
f.write(response.body)
self.log('Saved file %s' % fname)
pass
然后使用命令scrapy crawl demo运行爬虫,获取网页,在python123demo文件夹下会将捕获页面存储在demo.html中
scrapy爬虫的使用步骤:
Scrapy爬虫涉及到三个类:Request类(向网络上提交请求的内容),Response类(从网络中爬取内容的封装类),Item类(由SPIDERS产生的信息的封装类)
这些信息提取方法主要用在SPIDERS模块
在一个HTML页面的变量后边使用css().extract(),通过输入标签名称和标签属性来获得对应的标签信息
scrapy框架在setting.py中配置并发连接选项: