文章目录

  • 一、Python爬虫必备两大模块
  • 1.1 requests模块用于发送http请求
  • 1.2 bs4(beautifulsoup)模块用于解析html文本
  • 二、Python爬虫项目演示
  • 2.1 爬取红袖小说排行榜上的书籍图片


一、Python爬虫必备两大模块

1.1 requests模块用于发送http请求

模块介绍

requests是使用Apache2 licensed 许可证的HTTP库,使用python编写,比urllib2模块更简洁。

Request支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动响应内容的编码,支持国际化的URL和POST数据自动编码。

在python内置模块的基础上进行了高度的封装,从而使得python进行网络请求时,变得人性化,使用Requests可以轻而易举的完成浏览器可有的任何操作。

此外,requests会自动实现持久连接keep-alive

快速上手

  1. 导入模块
import requests
  1. 发送请求
import requests

r = requests.get('https://www.baidu.com')  # 最基本的不带参数的get请求
r1 = requests.get(url='https://www.baidu.com', params={'wd': 'python的requests模块'})  # 带参数的get请求

注意:可以使用不同的方法发送不同类型的请求:

requests.get(‘https://www.baidu.com’)  # GET请求
requests.post(“https://www.baidu.com”)  # POST请求
requests.put(“https://www.baidu.com”)  # PUT请求
requests.delete(“https://www.baidu.com”)  # DELETE请求
requests.head(“https://www.baidu.com”)  # HEAD请求
requests.options(“https://www.baidu.com” )  # OPTIONS请求
  1. 为url传递参数
url_params = {'key':'value'}  # 字典传递参数,如果值为None的键不会被添加到url中
r = requests.get('your url',params = url_params)
print(r.url)
  1. 响应的内容
# 属性:
r.encoding            # 获取当前的编码
r.encoding = 'utf-8'  # 设置编码
r.text                # 以encoding解析返回内容。字符串方式的响应体,会自动根据响应头部的字符编码进行解码。
r.content             # 以字节形式(二进制)返回。字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩。
r.headers             # 以字典对象存储服务器响应头,但是这个字典比较特殊,字典键不区分大小写,若键不存在则返回None
r.status_code         # 响应状态码
r.raw                 # 返回原始响应体,也就是 urllib 的 response 对象,使用 r.raw.read()   
r.ok                  # 查看r.ok的布尔值便可以知道是否登陆成功
r.history             # 返回重定向信息,当然可以在请求时加上allow_redirects = false 阻止重定向
r.requests.headers    # 返回发送到服务器的头信息

# 方法:
r.json()              # Requests中内置的JSON解码器,以json形式返回,前提返回的内容确保是json格式的,不然解析出错会抛异常
r.raise_for_status()  # 失败请求(非200响应)抛出异常
  1. 定制头和cookie信息
header = {'user-agent': 'my-app/0.0.1''}
cookie = {'key':'value'}
 r = requests.get/post('your url',headers=header,cookies=cookie) 
data = {'some': 'data'}
headers = {'content-type': 'application/json',
           'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}

r = requests.post('https://api.github.com/some/endpoint', data=data, headers=headers)
print(r.text)
  1. 设置请求超时
r = requests.get('url',timeout=1)  # 设置秒数超时,仅对于连接有效
  1. Session对象,能够跨请求保持某些参数
s = requests.Session()
s.auth = ('auth','passwd')
s.headers = {'key':'value'}
r = s.get('url')
  1. 代理
proxies = {'http':'ip1','https':'ip2'}
requests.get('url',proxies=proxies)

1.2 bs4(beautifulsoup)模块用于解析html文本

模块介绍

Beautiful Soup是python的一个HTML或XML的解析库,我们可以用它来方便的从网页中提取数据,它拥有强大的API和多样的解析方式

Beautiful Soup的三个特点:

  • Beautiful Soup提供一些简单的函数,用于浏览、搜索和修改解析DOM树,它是一个工具箱,通过解析文档为用户提供需要抓取的数据
  • Beautiful Soup自动将转入文档转换为Unicode编码,输出文档转换为UTF-8编码,不需要考虑编码,除非文档没有指定编码方式,这时只需要指定原始编码即可
  • Beautiful Soup位于流行的Python解析器(如lxml和html5lib)之上,可以尝试不同的解析策略或交易速度以获得灵活性

快速上手

  1. 结点选择器:
    直接调用节点的名称就可以选择节点元素,节点可以嵌套选择返回的类型都是bs4.element.Tag对象
soup=BeautifulSoup(html_doc,'lxml')
print(soup.head)  #获取head标签
print(soup.p.b) #获取p节点下的b节点
print(soup.a.string) #获取a标签下的文本,只获取第一个

name属性获取节点名称:

soup.body.name

attrs属性获取节点属性,也可以字典的形式直接获取,返回的结果可能是列表或字符串类型,取决于节点类型

soup.p.attrs    #获取p节点所有属性
soup.p.attrs['class']  #获取p节点class属性
soup.p['class']  #直接获取p节点class属性

string属性获取节点元素包含的文本内容:

soup.p.string   #获取第一个p节点下的文本内容

contents属性获取节点的直接子节点,以列表的形式返回内容

soup.body.contents   #是直接子节点,不包括子孙节点

children属性获取的也是节点的直接子节点,只是以生成器的类型返回

soup.body.children

descendants属性获取子孙节点,返回生成器

soup.body.descendants

parent属性获取父节点,parents获取祖先节点,返回生成器

soup.b.parent
soup.b.parents

next_sibling属性返回下一个兄弟节点,previous_sibling返回上一个兄弟节点,注意换行符也是一个节点,所以有时候在获取兄弟节点是通常是字符串或者空白

soup.a.next_sibling
soup.a.previous_sibling

next_siblings和previous_sibling分别返回前面和后面的所有兄弟节点,返回生成器

soup.a.next_siblings
soup.a.previous_siblings

next_element和previous_element属性获取下一个被解析的对象,或者上一个

soup.a.next_element
soup.a.previous_element

next_elements和previous_elements迭代器向前或者后访问文档解析内容

soup.a.next_elements
soup.a.previous_elements
  1. 方法选择器
    前面使用的都是通过节点属性来选择的,这种方法非常快,但在进行比较复杂的选择时就不够灵活,幸好Beautiful Soup还为我们提供了一些查询方法,如fang_all()和find()等
    find_all(name,attrs,recursive,text,**kwargs):查询所有符合条件的元素,其中的参数:
  • name表示可以查找所有名字为name的标签(tag),也可以是过滤器,正则表达式,列表或者是True
  • attrs表示传入的属性,可以通过attrs参数以字典的形式指定如常用属性id,attrs={‘id’:‘123’},由于class属性是python中的关键字,所有在查询时需要在class后面加上下划线即class_=‘element’,返回的结果是tag类型的列表
  • text参数用来匹配节点的文本,传入的形式可以是字符串也可以是正则表达式对象
  • recursive表示,如果只想搜索直接子节点可以将参数设为false:recursive=Flase
  • limit参数,可以用来限制返回结果的数量,与SQL中的limit关键字类似

find( name , attrs , recursive , text , **kwargs):它返回的是单个元素,也就是第一个匹配的元素,类型依然是tag类型,参数同find_all()一样

另外还有许多查询方法,其用法和前面介绍的find_all()方法完全相同,只不过查询范围不同,参数也一样

  • find_parents(name , attrs , recursive , text , **kwargs)find_parent(name , attrs , recursive , text , **kwargs):前者返回所有祖先节点,后者返回直接父节点
  • find_next_siblings(name , attrs , recursive , text , **kwargs)find_next_sibling(name , attrs , recursive , text , **kwargs):对当前tag后面的节点进行迭代,前者返回后面的所有兄弟节点,后者返回后面第一个兄弟节点
  • find_previous_siblings(name , attrs , recursive , text , **kwargs)find_previous_sibling(name , attrs , recursive , text , **kwargs):对当前tag前面的节点进行迭代,前者返回前面的所有兄弟节点,后者返回前面的第一个兄弟节点
  • find_all_next(name , attrs , recursive , text , **kwargs)和find_next(name , attrs , recursive , text , **kwargs):对当前tag之后的tag和字符串进行迭代,前者返回所有符合条件的节点,后者返回第一个符合条件的节点
  • find_all_previous()find_previous():对当前tag之前的tag和字符串进行迭代,前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点
  1. CSS选择器
    在 Tag 或 BeautifulSoup 对象的 .select()方法中传入字符串参数,即可使用CSS选择器的语法找到对应的tag。需要有一定的CSS基础,否则不太推荐使用
  2. tag修改方法
    Beautiful Soup可以实现改变tag标志的属性的值,添加或删除属性和内容
    Tag.append() 方法向tag中添加内容,类似Python的列表的 .append() 方法:
In [30]: soup.a
Out[30]: <a href="http://www.baidu.com/">百度</a>

In [31]: soup.a.append('一下')

In [32]: soup.a
Out[32]: <a href="http://www.baidu.com/">百度一下</a>

new_tag()方法用于创建一个tag标签:

In [33]: soup=BeautifulSoup('<b></b>','lxml')

In [34]: new_tag=soup.new_tag('a',href="http://www.python.org") #创建tag,第一个参数必须为tag的名称

In [35]: soup.b.append(new_tag) #添加到b节点下

In [36]: new_tag.string='python' #为tag设置值

In [37]: soup.b
Out[37]: <b><a href="http://www.python.org">python</a></b>

其他方法:

  • insert()将元素插入到指定的位置
  • inert_before()在当前tag或文本节点前插入内容
  • insert_after()在当前tag或文本节点后插入内容
  • clear()移除当前tag的内容
  • extract()将当前tag移除文档数,并作为方法结果返回
  • prettify()将Beautiful Soup的文档数格式化后以Unicode编码输出,tag节点也可以调用
  • get_text()输出tag中包含的文本内容,包括子孙tag中的内容
  • soup.original_encoding 属性记录了自动识别的编码结果
  • from_encoding表示参数在创建BeautifulSoup对象是可以用来指定编码,减少猜测编码的运行速度

二、Python爬虫项目演示

2.1 爬取红袖小说排行榜上的书籍图片

程序代码:

import requests
import bs4

# 1. 准备工作
headers = {  # 设置请求头信息(User-Agent),此操作为必须,否则http请求可能返回400的状态码,是一种反爬机制
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36"
}

# 2. 发送get请求并拿到响应内容
response = requests.get('https://www.hongxiu.com/rank', headers=headers)

# 3. 通过BeautifulSoup开始解析网页内容,使用lxml解析速度最快
soup = bs4.BeautifulSoup(response.content, 'lxml')

# 3.1 爬取各大榜单对应的页面url
pages = [i.attrs['href'] for i in soup.select("div.rank-nav-list a")]
# print(pages) 查看爬到的信息,发现a标签里面存的是uri
page_urls = ['https://www.hongxiu.com' + i for i in pages[1:]]  # 将uri加上域名变为url

# 3.2 去每个页面下爬取对应的书籍信息
for url in page_urls:
    res = requests.get(url, headers=headers)
    page_soup = bs4.BeautifulSoup(res.content, 'lxml')
    # 拿到图片url
    image_url = [i.attrs['src'] for i in page_soup.select("div.rank-body div.book-img-box img")]
    # 拿到书籍名称,用来做图片名
    image_name = [i.string for i in page_soup.select("h4 a")]

    # 4. 下载爬到的图片
    for i in range(len(image_url)):
        download = requests.get('https:' + image_url[i], headers=headers)
        print(image_name[i])
        with open("./images/" + image_name[i] + ".jpg", "bw") as file:
            file.write(download.content)

程序执行结果:

python抓取小红书热榜数据 python爬小红书_python抓取小红书热榜数据


参考:

Python—requests模块详解

python3解析库BeautifulSoup4