python网络爬虫需要什么库_【Python网络爬虫】01.爬虫原理,爬虫常用库入门练习...

爬虫原理和网页构造

网络连接原理:

计算机----Request(请求头和消息体)--->服务器

计算机

爬虫原理:

模拟计算机对服务器发起Request请求;

接收服务器的Response内容并解析、提取所需的信息

设计爬虫流程

多页面和跨页面爬虫流程。

多页面爬虫流程

网页存在多页的情况,每页结构相同或相似。

手动翻页观察各URL构成特点,构造成所有页面的URL存入列表;

根据URL列表依次循环取出URL;

定义爬虫函数;

循环调用爬虫函数,存储数据;

循环完毕,结束爬虫程序。

跨页面爬虫流程

一个页面存在很多链接,每个链接进去对应一个详情页。

定义爬虫函数爬取列表页所有专题的URL;

将专题URL存入列表中(种子URL);

定义爬取详细页数据函数;

进入专题详细页面爬取详细页数据;

存储数据,循环完毕,结束爬虫程序。

网页构造

浏览器按F12,点击Elements可以看到网页的元素,包括HTML、CSS、JavaScript

爬虫初步入门

创建虚拟环境

>mkvirtualenv Crawler

>workon Crawler

>pip install requests

>pip install lxml

>pip install beautifulsoup4

爬虫三大库

Requests库

它的作用就是请求网站获取网页数据的。

import requests

res = requests.get(url='https://blog.starmeow.cn/blog/1/detail/')

print(res) # ,如果为40x则请求失败

print(res.text) # 显示网页所有内容和F12结果一样

后端显示的浏览器Agent信息为:python-requests/2.20.0,意思就是通过requests库访问的

有时爬虫需要加入请求头来伪装成浏览器,以便更好地抓取数据。

image.png

请求头的使用方法

import requests

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

}

res = requests.get(url='https://blog.starmeow.cn/blog/1/detail/', headers=headers) # get方法加入请求头

print(res) # ,如果为40x则请求失败

print(res.text) # 显示网页所有内容和F12结果一样

然后再查看网页的请求Agent信息就是Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36

Requests库不仅有get()方法,还有post()方法。post()方法用于提交表单来爬取需要登录才能获取数据的网站。

错误和异常

Requests抛出一个ConnectionError异常,这个是网络问题(如DNS查询失败,拒绝连接等)

Response.raise_for_status()抛出一个HTTPError异常,为HTTP请求返回了不成功的状态码(如网页不存在,返回404错误)

Requests抛出一个Timeout异常,原因为请求超时

Requests抛出一个TooManyRedirects异常,为请求超过了设置的最大重定向次数

所有Requests显示抛出的异常都继承requests.exceptions.RequestException,爬取过程如果遇到错误爬虫就会停止,可以通过try来避免异常。

import requests

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

}

try:

res = requests.get(url='https://blog.starmeow0.cn/blog/1/detail/', headers=headers) # get方法加入请求头

print(res) # ,如果为40x则请求失败

print(res.text) # 显示网页所有内容和F12结果一样

except (ConnectionRefusedError, requests.exceptions.ConnectionError): # 出现错误会显示一下内容

print('拒绝连接')

当程序出现异常后,就不会直接报错,而是给一个提示,不会影响原来代码的运行。

BeautifulSoup库

可以轻松的解析Requests库请求的网页,并把网页源代码解析为Soup文档,以便过滤提取数据。

import requests

from bs4 import BeautifulSoup

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

}

try:

res = requests.get(url='https://blog.starmeow.cn/blog/1/detail/', headers=headers) # get方法加入请求头

soup = BeautifulSoup(res.text, 'html.parser')

print(soup.prettify())

except requests.exceptions.ConnectionError: # 出现错误会显示一下内容

print('拒绝连接')

看上去与res.text结果类似,但通过BeautifulSoup库解析得到的soup文档按照标准缩进格式的结构输出,为结构化的数据,为数据的过滤提取做好准备。

BeautifulSoup库的主要解析器

解析器

使用方法

优势

劣势

Python标准库

BeautifulSoup(markup, “html.parser”)

- Python的内置标准库- 执行速度适中- 文档容错能力强

Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差

lxml HTML 解析器

BeautifulSoup(markup, “lxml”)

- 速度快- 文档容错能力强

需要安装C语言库

lxml XML 解析器

BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”)

- 速度快- 唯一支持XML的解析器

需要安装C语言库

html5lib

BeautifulSoup(markup, “html5lib”)

- 最好的容错性- 以浏览器的方式解析文档- 生成HTML5格式的文档

速度慢,不依赖外部扩展

BeautifulSoup库官方推荐使用lxml作为解析器,效率更高。

标准选择器

find_all( name , attrs , recursive , text , **kwargs ) :可根据标签名、属性、内容查找文档

find( name , attrs , recursive , text , **kwargs ) :find返回单个元素,find_all返回所有元素

其他

find_all()方法

import requests

from bs4 import BeautifulSoup

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

}

try:

res = requests.get(url='https://blog.starmeow.cn/blog/1/detail/', headers=headers) # get方法加入请求头

soup = BeautifulSoup(res.text, 'html.parser')

# print(soup.prettify())

find_widget = soup.find_all('div', 'widget') # 查找class="widget"的所有div标签,最终结果以list方式展示

print(find_widget)

find_thumbnail = soup.find_all('span', attrs={'class': 'thumbnail'}) # attrs参数定义一个字典参数来所有包含特殊属性的tag,包含thumbnail的class的所有span

print(find_thumbnail)

except requests.exceptions.ConnectionError: # 出现错误会显示一下内容

print('拒绝连接')

find()方法

find()方法与find_all()方法类似,只是find_all()方法返回时文档汇总复核条件的所有tag,是一个集合(),find()方法返回的是一个Tag对象()

select()方法

从浏览器选择功能Copy selector,得到的结果用户信息的获取。

import requests

from bs4 import BeautifulSoup

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

}

try:

res = requests.get(url='https://blog.starmeow.cn/blog/1/detail/', headers=headers) # get方法加入请求头

soup = BeautifulSoup(res.text, 'html.parser')

title = soup.select("body > section > div > div > header > h1 > a") # 右键Elements位置---Copy---Copy selector

print(title) # [创建项目初始化]

hot_titles = soup.select("body > section > aside > div.widget.widget_hot > ul > li > a > span.text") # li:nth-child(1)运行会报错,需改为li

print(hot_titles)

"""

复制结果:

body > section > aside > div.widget.widget_hot > ul > li:nth-child(1) > a > span.text

结果会报错,需要进行修改

body > section > aside > div.widget.widget_hot > ul > li:nth-of-type(1) > a > span.text 得到第一个数据

body > section > aside > div.widget.widget_hot > ul > li > a > span.text 得到所有数据

"""

for title in hot_titles:

print(title, title.get_text(), title.get_text() == title.text)

"""

【Flask微电影】05.搭建前台页面-会员登录注册和会员中心 【Flask微电影】05.搭建前台页面-会员登录注册和会员中心 True

【Flask微电影】10.搭建后台页面-会员管理、评论管理 【Flask微电影】10.搭建后台页面-会员管理、评论管理 True

【Flask微电影】11.搭建后台页面-收藏管理、日志管理 【Flask微电影】11.搭建后台页面-收藏管理、日志管理 True

【Flask微电影】07.搭建后台页面-后台登陆、后台主页页面 【Flask微电影】07.搭建后台页面-后台登陆、后台主页页面 True

【Flask微电影】01.环境搭建项目目录分析 【Flask微电影】01.环境搭建项目目录分析 True

"""

except requests.exceptions.ConnectionError: # 出现错误会显示一下内容

print('拒绝连接')

使用title.get_text()或者title.text可以得到标签的文字信息

Lxml库

基于libxml2虚怀若谷人XML解析库的Python封装,使用C语言编写,解析速度比BeautifulSoup快。

实例1:爬取成都地区短租房信息

思路分析

分页url地址:

根据url构造,只需要改变p后面的数字,可以构造出所有页面网址。然后根据这些url进入到详情页,获取标题、地址、价格、房东等信息。

爬虫代码和注释

import requests

from bs4 import BeautifulSoup

import time

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

} # 用于伪装浏览器,便于爬虫的稳定性

def get_all_links(url):

"""

得到每个分页的房子url列表

:param url: 房源列表的分页url

:return: 得到每一页的所有房源列表

"""

html_data = requests.get(url=url, headers=headers)

soup = BeautifulSoup(html_data.text, 'lxml')

# print(soup)

links = soup.select('#page_list > ul > li > a')

res = list()

for link in links:

# print(link.get('href'))

href = link.get('href') # 获取标签href属性信息,得到进入详情页的URL

res.append(href)

time.sleep(2)

return res

def get_info(url):

"""

每一个房源信息获取

:param url: 房源url

:return: 房源字典信息

"""

html_data = requests.get(url, headers=headers)

soup = BeautifulSoup(html_data.text, 'lxml')

titles = soup.select('div.wrap.clearfix.con_bg > div.con_l > div.pho_info > h4 > em')

# 复制的结果是:body > div.wrap.clearfix.con_bg > div.con_l > div.pho_info > h4 > em,无法获取,需要去掉body

title = ''

if titles:

title = titles[0].get_text().strip() # 如果得到的结果不为空,取第一个的值

addresses = soup.select('div.wrap.clearfix.con_bg > div.con_l > div.pho_info > p > span')

# print(addresses)

address = ''

if addresses:

address = addresses[0].get_text().strip()

prices = soup.select('#pricePart > div.day_l > span')

price = ''

if prices:

price = prices[0].get_text()

images = soup.select('#curBigImage')

image = ''

if images:

image = images[0].get('src')

names = soup.select('#floatRightBox > div.js_box.clearfix > div.w_240 > h6 > a')

name = ''

if names:

name = names[0].get_text()

sexs = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > div')

sex = ''

if sexs:

sex = sexs[0].get('class')

# print(sex) # ['member_ico1']

if "member_ico1" in sex: # 根据class来判断房东的性别,男房东的class="member_ico"

sex = '女'

else:

sex = '男'

data = {

'title': title,

'address': address,

'price': price,

'image': image,

'name': name,

'sex': sex

}

# print(data)

return data

if __name__ == '__main__':

# fangzi_list = get_all_links('https://cd.xiaozhu.com/')

# fangzi_info = get_info('https://cd.xiaozhu.com/fangzi/2148542359.html')

page_urls = ['https://cd.xiaozhu.com/search-duanzufang-p{}-0/'.format(num) for num in range(1, 4)] # 准备3页数据

for page_url in page_urls:

fangzi_list = get_all_links(page_url) # 得到每一页的所有房源列表

time.sleep(2) # 暂停2秒,防止请求过快导致被服务器拒绝

for fangzi in fangzi_list:

print(get_info(fangzi)) # 遍历房源列表,得到每个房源信息

# 运行结果

# {'title': '宽窄巷子人民公园双地铁2号4号景区房熊猫风', 'address': '四川省成都市青羊区通惠门69号长富新城2栋24楼', 'price': '188', 'image': 'https://image.xiaozhustatic1.com/00,800,533/14,0,39,25214,1800,1200,71ccb694.jpg', 'name': '周周小家', 'sex': '男'}

# {'title': '地铁口春熙路太古里,熊猫基地大二居3床住5人', 'address': '四川省成都市成华区前锋路6号阳光欣园', 'price': '328', 'image': 'https://image.xiaozhustatic1.com/00,800,533/13,0,61,31508,1798,1200,d0c0cd6e.jpg', 'name': '幺妹家', 'sex': '女'}

实例2:爬取库存TOP500数据

思路分析

正好是第二页的列表,浏览发现,每一页显示22条数据,所以500条,23页能显示完

需要爬取的信息有排名、歌手、歌曲、歌曲时长

爬虫代码和注释

import requests

from bs4 import BeautifulSoup

import time

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"

} # 用于伪装浏览器,便于爬虫的稳定性

def get_info(url):

html_data = requests.get(url=url, headers=headers)

soup = BeautifulSoup(html_data.text, 'lxml')

ranks = soup.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_num') # 前3个数字加粗,select不能包含strong标签

# print(ranks[0].get_text().strip(), ranks[4].get_text().strip()) # 获取歌曲的信息

songs = soup.select('#rankWrap > div.pc_temp_songlist > ul > li > a')

length_of_times = soup.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_tips_r > span')

for rank, song, length_of_time in zip(ranks, songs, length_of_times):

data = {

'rank': rank.get_text().strip(), # 排名

'singer': song.get_text().split('-')[0].strip(), # 歌手

'name': song.get_text().split('-')[1].strip(), # 歌曲名

'url': song.get('href'), # 歌曲链接

'length_of_time': length_of_time.get_text().strip() # 时长

}

print(data)

return data

if __name__ == '__main__':

get_info('http://www.kugou.com/yy/rank/home/1-8888.html?from=rank')

top500_list = ['http://www.kugou.com/yy/rank/home/{}-8888.html?from=rank'.format(num) for num in range(1, 3)] # range(1, 24)显示所有页

for url in top500_list:

get_info(url)

time.sleep(2)

# 运行结果

# {'rank': '1', 'singer': '展展与罗罗', 'name': '沙漠骆驼', 'url': 'http://www.kugou.com/song/g3d726a.html', 'length_of_time': '5:38'}

# {'rank': '2', 'singer': '黑龙', 'name': '38度6', 'url': 'http://www.kugou.com/song/ootaieb.html', 'length_of_time': '3:11'}

# {'rank': '3', 'singer': '张紫豪', 'name': '可不可以', 'url': 'http://www.kugou.com/song/mkt6v7f.html', 'length_of_time': '4:00'}

# {'rank': '4', 'singer': 'G.E.M.邓紫棋', 'name': '光年之外', 'url': 'http://www.kugou.com/song/eoo8m01.html', 'length_of_time': '3:55'}

# {'rank': '5', 'singer': '半阳', 'name': '流浪', 'url': 'http://www.kugou.com/song/ndiin31.html', 'length_of_time': '3:39'}

zip()函数使用

描述

zip() 函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象。

如果各个可迭代对象的元素个数不一致,则返回的对象长度与最短的可迭代对象相同。

利用 * 号操作符,与zip相反,进行解压。

语法

zip() 函数语法:

zip(iterable1,iterable2, ...)

参数说明:

iterable -- 一个或多个可迭代对象(字符串、列表、元祖、字典)

返回的是一个对象,如果想要得到列表,可以用 list() 函数进行转换。

实例

>>> a = [1,2,3] #此处可迭代对象为列表

>>> b = [4,5,6]

>>> c = [4,5,6,7,8]

>>> zipped = zip(a,b)

>>> zipped

# #返回的是一个对象

>>> list(zipped)

# [(1, 4), (2, 5), (3, 6)] #使用list()函数转换为列表

>>> list(zip(a,c))

# [(1, 4), (2, 5), (3, 6)]

>>> zipped = zip(a,b)

>>> list(zip(*zipped)) #解压也使用list进行转换

# [(1, 2, 3), (4, 5, 6)]

#v1,v2,v3可是是任何可迭代对象,如:字符串、列表、元祖、字典

v1 = {1:11,2:22} #此处可迭代对象为字典

v2 = {3:33,4:44}

v3 = {5:55,6:66}

v = zip(v1,v2,v3) #压缩

print(list(v))

w = zip(*zip(v1,v2,v3)) #解压

print(list(w))

# [(1, 3, 5), (2, 4, 6)]

# [(1, 2), (3, 4), (5, 6)]

搭配for循环支持并行迭代

list1 = [2,3,4]

list2 = [4,5,6]

for x,y in zip(list1,list2):

print(x,y,'--',x*y)

# 2 4 -- 8

# 3 5 -- 15

# 4 6 -- 24

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值