爬虫学习(1)
前言
因科研需要,开始学习爬虫,对自己所学内容进行记录,若有错误之处,请大佬指正。本次内容多数是跟B站视频学习,立志从事爬虫开发者,可以去B站搜索相关视频学习。
一、爬虫的步骤
爬虫在百度百科上被定义为一种按照一定规律,自动地抓取万维网信息地程序或者脚本,其实我觉得可以简单地理解为用户自己模拟一个浏览器,让这个模拟的浏览器去获取网页内容,并将获取的内容以html源码的形式返回给用户。其步骤可以总的分为四部:
- 定义一个url,即你想爬取的网页地址
- 模拟浏览器向服务器发送请求(切记这个过程需要连网)
- 获取响应中的页面源码
- 打印数据
二、urllib库
urllib库是Python内置的一个基础库,不需要自己安装既可以使用的网络请求库
简单使用
import urllib.request
# 定义一个url
url = 'https://www.baidu.com'
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(url)
# 返回相应的内容
content = response.read().decode('utf8', 'ignore')
# 打印步骤
print(content)
这里只是按照爬虫的四个基本步骤的代码,就可以简单的获取到了网页的源码,这里使用浏览器开发模式查看,可以看到获取网页的源码和开发者模式下是相同的。其中urlopen方法是用来连接并获取输入的网页内容的,此方法的返回值是一个类文件句柄HTTPResponse对象,其下常用的方法有:
- read(size):此方法表示一字节一字节的打印获取到的网页源码,也可以通过设置size打印想输出的内容。
- readline():将获取的网页源码进行一行一行的读取。
- readlines():将获取的网页源码多行的读取
- getcode():获取网页的状态码,可以用此来判断是否能正常获取网页源码
- geturl():获取url地址
- getheaders():获取网页的状态信息
请求对象的定制
爬虫在向服务器发送爬取请求时,有些网页不允许被爬虫去访问网页内容,会返回出现错误等字样,这是常说的反扒。若想要继续获取网页内容,就需要采用一些反扒手段来规避这样问题,而User Agent请求头的定制就是常用的反扒手段。这里以百度网页为例。
import urllib.request
# 定义一个url
url = 'https://www.baidu.com'
# 请求头的定制
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/100.0.4896.88 Safari/537.36'
}
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 返回相应的内容
content = response.read().decode('utf8', 'ignore')
# 打印步骤
print(content)
headers的获取方法:打开浏览器的开发模式,选择Network项,在开发者模式下刷新页面,即可获取网页的headers,找到User-Agent复制即可得到。Request()方法用来进行对象的请求头的定制,就像是将User-Agent和url所携带的信息进行打包,可以将此函数返回结果看作一个包含多种信息的特殊url地址。当然在请求头定制当中不仅仅只包含User-Agent信息,还包括cookie等重要信息。
编解码
在某些时候你可能会访问带有中文参数的网页内容,如https://www.baidu.com/s?wd=周杰伦&sex=男,这样的网页信息,但是在定制url中直接使用此url地址,会在模拟浏览器向服务器发送请求时出现无法访问此网页地址的问题,因为在正常的浏览器中中文参数会自动进行编解码操作,再搜索的过程,如上面的url在浏览器中的真实地址应该是https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7,所有在爬虫中想要获取带参数的地址时,要向真实浏览器一样将参数进行编解码。
import urllib.request
import urllib.parse
# 定义一个url
url = 'https://www.baidu.com'
data = {
'wd': '周杰伦',
'sex': '男'
}
# get请求处理方法
a = urllib.parse.urlencode(data)
true_url = url + a
# 请求头的定制
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/100.0.4896.88 Safari/537.36'
}
request = urllib.request.Request(url=true_url, headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 返回相应的内容
content = response.read().decode('utf8', 'ignore')
# 打印步骤
print(content)
parse是urllib库提供的工具模块,提供了很对url处理方法,如上使用的是urlencode()方法进行中文参数编解码。此为在post请求的网页中,对带有参数的网页必须进行解编码操作,并且需要在urlencode方法后加上其编码方式,如urlencode(data).encode(‘utf-8’)。
解析服务器响应内容
经过上述获取到的网页内容,是整个网页的源码,其中可能会包含很多我们不需要的内容,为了能够准确获取我们想要获取的内容,需要对获取的网页内容进行解析,这里介绍是使用Xpath解析方法。
首先,需要在浏览器中安装Xpath插件(请自行在网上搜索安装步骤以及使用方法),之后再使用pip安装lxml库。这里罗列了一些常用的xpath语法。
表达式 | 功能描述 |
// | 从当前节点获取子孙节点 |
/ | 从当前节点选择其直接直接点(如://ul/li) |
. | 选择当前节点 |
@ | 以属性值查找 |
下面给出解析“百度一下”字体的内容代码
from lxml import etree
import urllib.request
# 获取百度一下四个字
# 定义一个网址
url = 'https://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/100.0.4896.88 Safari/537.36'
}
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器获取数据
response = urllib.request.urlopen(request)
all_content = response.read().decode('utf8', 'ignore')
# 使用lxml解析
tree = etree.HTML(all_content)
# 解析后的数据返回为列表形式
part_content = tree.xpath('//div/b[@class=\'cur-tab\']/text()')[0]
print(part_content)
若你不了解HTML或CSS的基本知识可能会对xpath方法难以理解,可以选择使用BeautifulSoup这里tree.xpath返回的是列表形式,最后给出爬取站长素材前十页的风景图片的模块化编程例子,以供进行参考和复习。
import urllib.request
from lxml import etree
# https://sc.chinaz.com/tupian/huadetupian.html
# https://sc.chinaz.com/tupian/huadetupian_2.html
def create_request(start_page, end_page):
"""
:param start_page:
:param end_page:
:return:
"""
for i in range(start_page, end_page + 1):
if i == 1:
url = 'https://sc.chinaz.com/tupian/huadetupian.html'
else:
url = 'https://sc.chinaz.com/tupian/huadetupian_' + str(i) + '.html'
headers = {
'User-Agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) '
'Chrome / 100.0.4896.75 Safari / 537.36 Edg / 100.0.1185.39'
}
# 返回网页对象在内存中的临时地址
request = urllib.request.Request(url=url, headers=headers)
return request
def create_response(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf8', 'ignore')
return content
def get_print(content):
# 解析服务器的内容
tree = etree.HTML(content)
pic_name = tree.xpath('//div[@id="container"]//div/a/@alt')
part_url = tree.xpath('//div[@id="container"]//div//img/@src2')
for i in range(len(part_url)):
url = 'https:' + part_url[i]
print(pic_name[i], url)
if __name__ == '__main__':
start_page = int(input("请输入起始页面:"))
end_page = int(input("请输入结束页面:"))
# 请求对象定制
request = create_request(start_page, end_page)
# 返回源网页
content = create_response(request)
# 浏览图片名称和地址
get_print(content)