文章目录
- 什么是爬虫?
- python爬虫的基本架构
- urllib库request模块 实现下载网页的三种方式
- urllib库 parse模块
- http库 cookiejar模块
- 正则表达式 re模块
- 实例:爬取网页中的图片
什么是爬虫?
一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。
python爬虫的基本架构
Python 爬虫架构主要由五个部分组成,分别是调度器、URL管理器、网页下载器、网页解析器、应用程序(爬取的有价值数据)。
功能 | |
调度器 | 相当于一台电脑的CPU,主要负责调度URL管理器、下载器、解析器之间的协调工作。 |
URL管理器 | 包括待爬取的URL地址和已爬取的URL地址,防止重复抓取URL和循环抓取URL,实现URL管理器主要用三种方式,通过内存、数据库、缓存数据库来实现。 |
网页下载器 | 通过传入一个URL地址来下载网页,将网页转换成一个字符串,网页下载器有urllib库中的request模块 |
网页解析器 | 将一个网页字符串进行解析,可以按照我们的要求来提取出我们有用的信息,也可以根据DOM树的解析方式来解析。网页解析器有正则表达式(直观,将网页转成字符串通过模糊匹配的方式来提取有价值的信息,当文档比较复杂的时候,该方法提取数据的时候就会非常的困难)、html.parser(Python自带的)、beautifulsoup(第三方插件,可以使用Python自带的html.parser进行解析,也可以使用lxml进行解析,相对于其他几种来说要强大一些)、lxml(第三方插件,可以解析 xml 和 HTML),html.parser 和 beautifulsoup 以及 lxml 都是以 DOM 树的方式进行解析的。 |
应用程序 | 就是从网页中提取的有用数据组成的一个应用。 |
urllib库request模块 实现下载网页的三种方式
- urlopen()函数
urllib.request.urlopen(url, data=None, [timeout, ])
传入的url就是你想抓取的地址
data是指向服务器提交信息时传递的字典形式的信息,通常来说就是爬去需要登录的网址时传入的用户名和密码,可省略。
timeout参数指的是超时时间,也可省略。
import urllib.request as eq
url = "http://www.baidu.com"
file = eq.urlopen(url).read() #直接读取信息
path = open("C:\\users\\32259\\Desktop\\baidu.txt","wb") #以写入二进制方式创建文件对象
path.write(file) #写入爬取的信息
path.close() #关闭文件
在抓取网页的时候,我们会遇到一些反爬虫的设置,比如说服务器读取到请求为爬虫时会出现403错误,这是我们就需要伪装成为浏览器来访问,此时要添加头信息。在network(网络)的选项中选取user-agent选项,复制下来。
伪装浏览器进行爬虫,添加头信息
import urllib.request as eq
url = "http://www.baidu.com"
request = eq.Request(url) #创建Request对象
request.add_header("user-agent","Mozilla/5.0") #添加头信息
file = eq.urlopen(request).read() #读取信息
path = open("C:\\users\\32259\\Desktop\\baidu.txt","wb") #以写入二进制方式创建文件对象
path.write(file) #写入爬取的信息
path.close() #关闭文件
如果遇到更厉害的反扒手段,发现某一个IP频繁访问网址,会被服务器屏蔽,那么该怎么办呢?这是就需要代理服务器上场了。
百度随便搜一个代理服务器
代理服务器模拟浏览器进行爬虫
import urllib.request as eq
url = "http://www.baidu.com"
request = eq.Request(url) #创建Request对象
request.add_header("user-agent","Mozilla/5.0") #添加头信息
IP = eq.ProxyHandler("HTTP":123.73.81.224:32221) #设置代理服务器信息
opener = eq.build_opener(IP,eq.HTTPHandler) #自定义打开方式,传入代理服务器信息和HTTPHandler类
file = opener.open(request).read() #读取信息
path = open("C:\\users\\32259\\Desktop\\baidu.txt","wb") #以写入二进制方式创建文件对象
path.write(file) #写入爬取的信息
path.close() #关闭文件
urllib库 parse模块
post请求,即模拟登陆。所谓模拟登陆,当然需要输入账号和密码了,在urllib库中该如何编写代码呢?假设我们登陆某个网站,需要提交用户名和密码,在这里我们假设id:小明,密码:123456
引入解析模块:urllib.parse
import urllib.request as eq
import urllib.parse as pa
url='www.haha.com'#假设的网站网址
post=pa.urlencode({'id':'明明','password':'123456'}).encode('utf-8')
req=eq.Request(url,post)#传入用户名和密码,并使用urlencode编码字典,再设置为utf-8编码
req.add_header("user-agent","Mozilla/5.0")#添加头信息
data=eq.urlopen(req).read()
print(len(data))
http库 cookiejar模块
爬虫是不会自动保存cookie 的 ,因此我们需要手动设置
import http.cookiejar as co#导入模块
import urllib.request as eq
scookie=co.CookieJar()#创建对象
opener=eq.buile_opener(eq.HTTPCookieProcessor(scookie))#传入创建的对象
opener.open(url)
正则表达式 re模块
- findall(“匹配规则”,“被匹配字符串”):找到re匹配的所有字符串,并把他们作为一个列表返回
- finditer():找到re匹配的所有字符串,并把他们作为一个迭代器返回,需要进行循环遍历,调用group()方法看值
- search():扫描字符串,找到这个re匹配的位置
- match():决定re是否在字符串刚开始的位置匹配
- 如果没有匹配到的话,match()和search()将返回None,成功则返回“match Object”实例,想要看值,得调用group()方法
a = re.compile('匹配规则'[,re.I]):返回一个正则对象,后面表示不区分大小写
a.findall('被匹配的字符串')
规则 | 作用 |
[] | 中括号中的内容会被逐一匹配 |
. | 匹配除换行符外任何的字符 |
^ | 匹配字符串开始的部分(是否以什么开头) |
$ | 匹配字符串结束的部分(是否以什么结尾) |
\w | 匹配任意字母、数字、下划线[0-9a-zA-Z_] |
\W | ![0-9a-zA-Z_] |
\d | 匹配单个十进制数字 |
\D | 匹配十进制数字以外的字符 |
\s | 匹配空白字符 如:空格,tab键 |
匹配两个不同的字符串 | |
() | 模式单元符:将括号里的看作一个字符匹配,一般与其他匹配规则一起使用 |
* | 匹配左邻字符出现0次或多次 |
+ | 匹配左邻字符出现1次或多次 |
? | 左邻字符出现0次或者1次 |
{n[,m]} | 只有n时,匹配左邻字符恰好出现n次;两个都有时,匹配左邻字符至少出现n次,至多出现m次 |
编译选项指定:
- re.I:忽略大小写
- re.L:使用预定字符类\w\W\b\B\s\S取决当前区域设定
- re.M:多行模式改变^和$的行为
- re.S:.任意匹配模式
- re.U:使用预定字符类\w\W\b\B\s\S\d\D取决Unicode定义的字符属性
- re.X:详细模式,可以多行,忽略空白字符,并且可以加入注释
贪婪模式和非贪婪模式:
正则表达式通常用于在文本中查找匹配的字符串。Python里的数量词默认是贪婪的,意思是总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。
例如∶正则表达式“ab*”如果用于查找“abbbc”,将找到“abbb”。而如果使用非贪婪方法“ab*?”,将找到“a”。
实例:爬取网页中的图片
首先打开你要爬取的网页,这里以京东的皮卡丘商品为例:
然后打开审查元素,查看图片的url信息:
根据url信息编写相应的正则表达式:建议多拿几个对比发现规则
开始编写代码:
思路:首先爬到对应的网页,然后再从这些网页信息中找到自己想要的图片信息,然后完善图片的url,通过url再去爬图片
import re
import urllib.request as eq
class Get_Worm:
#有参构造
def __init__(self,URL,HEAD):
self.url = URL
self.head = HEAD
def get_file(self):
#下载网页内容
self.req = eq.Request(self.url)
self.req.add_header("user-agent", self.head)
respon = eq.urlopen(self.req)
return respon.read()
def get_list(self):
#解析下载好的网页,提取图片信息
self.endlist = []
imagelist = re.findall(b"//img\d{2}.360buyimg.com/n7/jfs/t1/.{1,}.jpg", self.get_file())
for i in imagelist:
self.endlist.append("http:" + str(i, encoding="utf8"))
return self.endlist
def get_image(self):
#下载图片的方法
num = 0
for self.url in self.get_list():
print(self.url)
num += 1
with open("C:\\Users\\32259\\Desktop\\image\\"+str(num)+".jpg","wb") as f:
f.write(self.get_file())
url = "https://search.jd.com/Search?keyword=%E7%9A%AE%E5%8D%A1%E4%B8%98&enc=utf-8&wq=%E7%9A%AE%E5%8D%A1%E4%B8%98&pvid=9002b2ae3baf4cf4b74ccbe83d855624/"
html = Get_Worm(url,"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
html.get_image() #调用
执行程序:爬取成功!