【Python爬虫实战】爬取某小说网排行榜上的图书封面图片

一、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
    
  2. 发送请求

    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请求
    
  3. 为url传递参数

    url_params = {'key':'value'}  # 字典传递参数,如果值为None的键不会被添加到url中
    r = requests.get('your url',params = url_params)
    print(r.url)
    
  4. 响应的内容

    # 属性:
    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响应)抛出异常
    
  5. 定制头和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)
    
  6. 设置请求超时

    r = requests.get('url',timeout=1)  # 设置秒数超时,仅对于连接有效
    
  7. Session对象,能够跨请求保持某些参数

    s = requests.Session()
    s.auth = ('auth','passwd')
    s.headers = {'key':'value'}
    r = s.get('url')
    
  8. 代理

    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
    
  2. 方法选择器
    前面使用的都是通过节点属性来选择的,这种方法非常快,但在进行比较复杂的选择时就不够灵活,幸好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和字符串进行迭代,前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点

  3. CSS选择器
    在 Tag 或 BeautifulSoup 对象的 .select()方法中传入字符串参数,即可使用CSS选择器的语法找到对应的tag。需要有一定的CSS基础,否则不太推荐使用

  4. 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—requests模块详解

python3解析库BeautifulSoup4

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值