前言
感觉爬虫很有意思,来进行一下简单学习。途中遇见很多bug,在后文中会逐一讲解。
常用模块
Python爬虫常用的模块有以下几个
1、requests 用于请求网站
2、bs4 用于
3、re 用于正则匹配(python自带,无需安装)
一般安装某个模块的话,指令常常是pip install xxx
这种,但是由于国内有时候无法访问国外的一些资源,因此我们这里往往需要去借用国内的镜像源,可以直接在本地设置好镜像源,一劳永逸,也可以每次执行命令都附带镜像源网站,这里介绍一下本地设置镜像源的方法
1、按下win+r键,打开运行
2、搜索%appdata%
3、在此目录下新建一个文件夹,命名为pip
4、在pip
文件夹内创建一个php.ini
文件,文件内容如下
[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host=pypi.douban.com
保存后退出即可
这里的话镜像源就配置好了,我们此时就可以去安装模块了
以管理员身份运行cmd,输入
pip install requests
下载完成,后输入
python
import requests
若如下图,即无回显则说明安装完成
安装bs4模块的时候,用pip install bs4
总是出现安装完成但是无法调用的模块,试了试发现下面这个指令可以避免这种情况的出现,因此大家可以试着用下面的这种方法来安装bs4模块
python -m pip install beautifulsoup4
安装后同上,输入
python
import bs4
若无回显则说明安装完成
爬取网页图片
这里先从简单点的入手,先不用bs4模块,只用requests模块
编写爬虫的话,肯定是用Python来访问某个网站的,网站的话我们需要注意不能爬取付费网站
其次就是有些网站会禁止python请求,这个时候我们需要伪造一个User-Agent
头来爬取网站,UA头可以通过F12中找出
也可以利用burpsuite抓包获取
对于爬取的东西,我们这里是爬取表情包,我们这里可以通过 右键,点击检查来获取表情包对应的前端代码
发现格式是这种
<img src="xxx" alt="xxx" width="160" height="120">
因此这里的话,我们就可以通过正则匹配来表示所有的表情包,也就是
<img src="(.*)" alt="(.*)" width="160" height="120">
来表示所有的表情包
其他的话也没什么需要特别说明的了
具体的代码如下所示
import requests#调用requests模块用于进行网页请求
import re#调用re模块用于正则匹配
import os#调用os模块执行命令
image = '表情' #存放爬取表情的文件夹名称
if not os.path.exists(image):#用if语句判断是否存在这个文件夹
os.mkdir(image)#不存在此目录的话就创建一个
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' #伪造UA请求头,有的网站会禁止python请求
}
response = requests.get('https://qq.yh31.com/zjbq/', headers=headers)#以GET方式请求网站
response.encoding = 'GBk' #编码方式
response.encoding = 'UTF-8' #编码方式
print(response.request.headers)#输出请求头信息
print(response.status_code)#输出状态码
t = '<img src="(.*?)" alt="(.*?)" width="160" height="120">' #这里的话就是利用正则匹配将全部表情包表达出来,.匹配除/n/r的任意单个字符,而*是匹配前面的表达式零次或多次,?是指匹配前面的零次或一次,也就是非贪婪模式
result = re.findall(t, response.text)#这个是将response.text中所有与t格式相匹配的字符串取出,赋值给result变量,返回形式为数组
print(result)
for img in result: #用for循环将每个表情包进行遍历
print(img) #输出每个信息,即每个表情包的表情包链接和表情包名
res = requests.get(img[0],headers=headers)#获取表情包链接
print(res.status_code) #输出请求状态码
s = img[0].split('.')[-1]#获取后缀格式,如jpg,gif
with open(image + '/' + img[1] + '.' + s,'wb') as f: #写入到表情,传入标识符'w'或者'wb'表示写文本文件或写二进制文件:
f.write(res.content)#文件的写入操作
结果如下图
还有这里需要说明一点,就是如果报出错误是
Traceback (most recent call last):
File "d:\python测试\pa.py", line 11, in <module>
response = requests.get('https://qq.yh31.com/zjbq/', headers=headers)#以GET方式请求网站
File "D:\Python\lib\site-packages\requests\api.py", line 75, in get
return request('get', url, params=params, **kwargs)
File "D:\Python\lib\site-packages\requests\api.py", line 61, in request
return session.request(method=method, url=url, **kwargs)
File "D:\Python\lib\site-packages\requests\sessions.py", line 529, in request
resp = self.send(prep, **send_kwargs)
File "D:\Python\lib\site-packages\requests\sessions.py", line 645, in send
r = adapter.send(request, **kwargs)
File "D:\Python\lib\site-packages\requests\adapters.py", line 517, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='qq.yh31.com', port=443): Max retries exceeded with url: /zjbq/ (Caused by SSLError(SSLEOFError(8, 'EOF occurred in violation of protocol (_ssl.c:1122)')))
这种的话,不是由于网站的证书有问题,而是由于你开了代理的问题,关闭代理就可以解决问题了
这里再爬取一个网站的表情包(免费表情包网站),链接如下https://www.pkdoutu.com/
import requests#调用requests模块用于进行网页请求
import re#调用re模块用于正则匹配
import os#调用os模块执行命令
def say():
image = '表情' #存放爬取表情的文件夹名称
if not os.path.exists(image):#用if语句判断是否存在这个文件夹
os.mkdir(image)#不存在此目录的话就创建一个
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' #伪造UA请求头,有的网站会禁止python请求
}
response = requests.get('https://www.pkdoutu.com/', headers=headers)#以GET方式请求网站
response.encoding = 'GBk' #编码方式
response.encoding = 'UTF-8' #编码方式
print(response.request.headers)#输出请求头信息
print(response.status_code)#输出状态码
t = '<img referrerpolicy="no-referrer" class="lazy image_dtb img-responsive" src="(.*?)" data-original="(.*?)" data-backup="(.*?)" alt="">' #这里的话就是利用正则匹配将全部表情包表达出来,.匹配除/n/r的任意单个字符,而*是匹配前面的表达式零次或多次,?是指匹配前面的零次或一次,也就是非贪婪模式
#print(response.text)
result = re.findall(t, response.text)#这个是将response.text中所有与t格式相匹配的字符串取出,赋值给result变量,返回形式为数组
print(result)
for img in result: #用for循环将每个表情包进行遍历
print(img) #输出每个信息,即每个表情包的表情包链接和表情包名
res = requests.get(img[1],headers=headers)#获取表情包链接
print(res.status_code) #输出请求状态码
s = img[1].split('.')[-1]#利用python的切片获取后缀格式,如jpg,gif
with open(image + '/' + img[1].split('/')[-1] ,'wb') as f: #写入到表情,传入标识符'w'或者'wb'表示写文本文件或写二进制文件:
f.write(res.content)#文件的写入操作
爬取网页内容(requests+bs4)
这里假设一个题目,需要去爬取百度界面的帮助中心
要求
1、调用requests模块和bs4模块
2、代码中不出现汉字
在写代码之前,我们不妨先简单学习一下Bs4模块
浅学Bs4
beautifulSoup是将网页源代码转换为树的形式,网页源代码中的标签,就是树的节点,节点中就会有我们所需要的内容。
调用它,首先我们需要将请求到的文本转换一下(转换为树结构)
soup = BeautifulSoup(r.text, "html.parser")
HTML中存在的<a>,<li>
等标签,我们这里想获取其标签中的内容的话,用soup.a ,soup.li
就可以实现
每个标签都有自己的属性attr
soup.a.attrs 表示获取a标签下的全部属性
soup.a['div'] 表示获取a标签下属性为div的内容
常用的解析网页代码方式,有三种
1、find
2、find_all
3、select
find只返回第一个匹配到的对象
语法:
find(name, attrs, recursive, text, **wargs)
#name 查找标签
#attrs 查找属性
#text 查找文本
#recursive 递归的,循环的
示例
# find查找一次
li = soup.find('li')
print('find_li:',li)
print('li.text(返回标签的内容):',li.text)
print('li.attrs(返回标签的属性):',li.attrs)
print('li.string(返回标签内容为字符串):',li.string)
运行结果
find_li: <li class="item-0" id="flask"><a href="link1.html">first item</a></li>
li.text(返回标签的内容): first item
li.attrs(返回标签的属性): {'id': 'flask', 'class': ['item-0']}
li.string(返回标签内容为字符串): first item
由于class
是Python的保留关键字,因此调用它时需要特殊方法,方式有以下两种
1、在attrs属性用字典的方式进行参数传递
2、BeautifulSoup自带的特别关键字class_
示例
# 第一种:在attrs属性用字典进行传递参数
find_class = soup.find(attrs={'class':'item-1'})
print('findclass:',find_class,'\n')
# 第二种:BeautifulSoup中的特别关键字参数class_
beautifulsoup_class_ = soup.find(class_ = 'item-1')
print('BeautifulSoup_class_:',beautifulsoup_class_,'\n')
运行结果
findclass: <li class="item-1"><a href="link2.html">second item</a></li>
BeautifulSoup_class_: <li class="item-1"><a href="link2.html">second item</a></li>
find_all
返回所有匹配到的结果,区别于find(find只返回查找到的第一个结果)
语法
find_all(name, attrs, recursive, text, limit, **kwargs)
示例
# find_all 查找所有
li_all = soup.find_all('li')
for li_all in li_all:
print('---')
print('匹配到的li:',li_all)
print('li的内容:',li_all.text)
print('li的属性:',li_all.attrs)
运行结果
---
匹配到的li: <li class="item-0" id="flask"><a href="link1.html">first item</a></li>
li的内容: first item
li的属性: {'id': 'flask', 'class': ['item-0']}
---
匹配到的li: <li class="item-1"><a href="link2.html">second item</a></li>
li的内容: second item
li的属性: {'class': ['item-1']}
---
匹配到的li: <li cvlass="item-inactie"><a href="link3.html">third item</a></li>
li的内容: third item
li的属性: {'cvlass': 'item-inactie'}
---
匹配到的li: <li class="item-1"><a href="link4.html">fourth item</a></li>
li的内容: fourth item
li的属性: {'class': ['item-1']}
---
匹配到的li: <li class="item-0"><a href="link5.html">fifth item</a>
</li>
li的内容: fifth item
select
语法
select(self, selector, namespaces=None, limit=None, **kwargs)
示例
soup.select('title')#获取title标签
soup.select('title > p')#获取title下的p标签
编写脚本
不难发现它位于div
标签,s-bottom-layer-content
属性中的第四个
# -*- coding:utf-8 -*-
import requests,urllib
from bs4 import BeautifulSoup
url="http://www.baidu.com"
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' #伪造UA请求头,有的网站会禁止python请求
}
r = requests.get(url,headers=headers)#网站请求
soup = BeautifulSoup(r.text,"html.parser")#使用bs4转换为树结构
content = soup.find("div",class_="s-bottom-layer-content").contents[3].text#查找div标签下属性是s-bottom-layer-content的,然后输出它第四个的文本
print(content)
当然,你也可以用find_all来匹配p标签
,lh属性
下的第四个
# -*- coding:utf-8 -*-
import requests,urllib
from bs4 import BeautifulSoup
url="http://www.baidu.com"
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' #伪造UA请求头,有的网站会禁止python请求
}
r = requests.get(url,headers=headers)#网站请求
soup = BeautifulSoup(r.text,"html.parser")#使用bs4转换为树结构
content = soup.find_all("p",class_="lh")[3].text#查找p标签下属性是lh的,然后输出它第四个的文本
print(content)
或使用select
# -*- coding:utf-8 -*-
import requests,urllib
from bs4 import BeautifulSoup
url="http://www.baidu.com"
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' #伪造UA请求头,有的网站会禁止python请求
}
r = requests.get(url,headers=headers)#网站请求
soup = BeautifulSoup(r.text,"html.parser")#使用bs4转换为树结构
content = soup.select('div > p')[3].text#查找div标签下p标签,然后输出它第四个的文本
print(content)
参考文献
https://blog.csdn.net/qq_46145027/article/details/123969044
https://blog.csdn.net/WuLex/article/details/88563332
https://www.cnblogs.com/ymjyqsx/p/6554817.html
https://www.cnblogs.com/xieshengsen/p/6727064.html
https://blog.csdn.net/weixin_42970378/article/details/83108206
https://blog.csdn.net/qq_40589051/article/details/90579064
https://blog.csdn.net/wei_lin/article/details/102334956