Python爬虫超详细基础知识:从请求到解析再到数据保存(附完整实战案例)

> 本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

一.引言

在当今信息爆炸的时代,网络爬虫成为了获取和处理网络数据的重要工具。Python,以其简洁的语法和强大的库支持,成为了编写爬虫的首选语言。本文将详细介绍如何使用Python进行网络爬虫的编写,包括发送请求、解析数据以及保存结果。

二.环境准备

#发请求的库
pip install requests
#解析库
pip install parsel

三.知识点概述(附案例)

(一)requestst概述

requests模块是一个网络请求模块,可以帮助我们模拟成客户端去请求服务器的数据。 我们可以在浏览器中抓取到这些请求与响应的内容,那么我们可以“伪造”请求吗?也就是不再通过浏览器发送这些数据,而是通过Python来模拟浏览器发送请求。答案是可行的。而Requests模块就可以完成这种功能。 还有其他库吗? 回答也是肯定的,例如 urllib , urllib2 等模块。但是目前来说 Requests 模块是最流行的。而且也是做好用的模块。

(二)请求方法

1.get 请求

一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用 get 请求。

import requests
#案例链接:https://movie.douban.com/top250
headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }

url = "https://movie.douban.com/top250"
params = {
     "start": "0",
     "filter": ""
 }
 response = requests.get(url, headers=headers, params=params)
2.post 请求

向服务器发送数据(登录)、上传文件等,会对服务器资源产生影响的时候会使用post 请求。

(1)Form Data 模式

post请求请求参数Form Data ---------------------------------> 用data关键字传递
​​​​在这里插入图片描述
在这里插入图片描述

import requests
#案例链接:https://www.kfc.com.cn/kfccda/storelist/index.aspx
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx'
params = {'op': 'keyword'}  # 查询参数
data = {  # 请求参数
    'cname': '',
    'pid': '',
    'keyword': '北京',
    'pageIndex': '1',
    'pageSize': '10'
}

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'}

# data是构建post请求的请求参数关键字
response = requests.post(url=url, params=params, data=data, headers=headers)
(2)Request Payload 模式

post请求请求参数Request Payload ---------------------------------> 用json关键字传递
在这里插入图片描述
在这里插入图片描述

import requests
#案例链接:https://www.zfcg.sh.gov.cn/site/category?parentId=137027&childrenCode=ZcyAnnouncement&utm=site.site-PC-39935.959-pc-websitegroup-navBar-front.3.e7740270bd1411ef87a395a2e57c85a7

url = 'http://www.zfcg.sh.gov.cn/portal/category'

json_data = {"pageNo": 1, "pageSize": 15, "categoryCode": "ZcyAnnouncement1", "_t": 1734505402000}

# json 以json数据提交的请求参数
response = requests.post(url=url, json=json_data)

(三)解析语法

1.css选择器
(1)标签、类和id选择器
  1. 标签选择器其实就是我们经常说的html代码中的标签。例如htmlspanpdivaimg等等
  2. 类选择器在我们今后的css样式编码中是最常用到的,它是通过为元素设置单独的class来赋予元素样式效果。
  3. D选择器类似于类选择符,作用同类选择符相同,但也有一些重要的区别。
选择器例子例子描述
.class.intro选择 class=“intro” 的所有元素。
#id#firstname选择 id=“firstname” 的所有元素。
**选择所有元素。
elementp选择所有

元素。

element,elementdiv,p选择所有
元素和所有

元素。

element elementdiv p选择
元素内部的所有

元素。

element>elementdiv>p选择父元素为
元素的所有

元素。

[attribute][target]选择带有 target 属性所有元素。
(2)伪类选择器
语法示例描述
:last-of-typep:last-of-type选择满足p语法元素的最后一个元素
:not(selector):not§选择所有p以外的元素
:nth-child(n)p:nth-child(2)选择满足p语法元素的第二个元素
:nth-last-child(n)p:nth-last-child(2)选择满足p语法元素的倒数的第二个元素

接着上述get请求做css语法解析
在这里插入图片描述
在这里插入图片描述

import csv
import requests
import parsel

def get_data(page):
    print(f'==============正在抓取{page}页===================')
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }

    url = "https://movie.douban.com/top250"
    params = {
        "start": f"{(page-1)*25}",
        "filter": ""
    }
    response = requests.get(url, headers=headers, params=params)

    parsel_text = parsel.Selector(response.text)
      ##css语法解析
    lis = parsel_text.css('.grid_view li')  #一次提取

	#二次提取
    for li in lis:
        movie_name = li.css('.title:nth-child(1)::text').get() #标题
        movie_score = li.css('.star .rating_num::text').get() #评分
        info = li.css('.bd>p::text').getall()
        info = [i.strip().replace('\xa0','') for i in info]
        info1 = info[1].split('/')
        movie_time = info1[0]
        movie_area = info1[-2]
        movie_type = info1[-1]

        print({
           'movie_name' :movie_name,
           'movie_score' :movie_score,
           'movie_time' :movie_time,
           'movie_area' :movie_area,
           'movie_type' :movie_type,
        })
        

if __name__ == '__main__':
    
    for page in range(1,11):
        get_data(page)

2.xpath节点提取
										认识树的结构

在这里插入图片描述
认识xpath的节点关系
在这里插入图片描述

(1)xpath语法

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

下面列出了最有用的表达式:

表达式描述
nodename选中该元素。
/从根节点选取、或者是元素和元素间的过渡。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。跨节点获取标签
.选取当前节点。
选取当前节点的父节点。
@定位, 选取属性值
text()选取文本。

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式结果
bookstore选择bookstore元素。
/bookstore选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book选取属于 bookstore 的子元素的所有 book 元素。
//book选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//book/title/@lang选择所有的book下面的title中的lang属性的值。
//book/title/text()选择所有的book下面的title的文本。
  • 选取未知节点
通配符描述
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式结果
/bookstore/*选取 bookstore 元素的所有子元素。
//*选取文档中的所有元素。
//title[@*]选取所有带有属性的 title 元素。

接着上述get请求做xpath语法解析
在这里插入图片描述


import requests
from parsel import Selector

def get_data(page):
    print(f'==============正在抓取{page}页===================')
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }

    url = "https://movie.douban.com/top250"
    params = {
        "start": f"{(page-1)*25}",
        "filter": ""
    }
    response = requests.get(url, headers=headers, params=params)

    selector = Selector(response.text)
    
    ##xpath语法解析
    lis = selector.xpath('//ol[@class="grid_view"]/li')

    for li in lis:
        movie_name = li.xpath('.//div[@class="info"]/div[@class="hd"]/a/span[1]/text()').get()  # 标题
        movie_score = li.xpath('.//span[@class="rating_num"]/text()').get()  # 评分
        info = li.xpath('.//div[@class="bd"]/p/text()').getall()
        info = [i.strip().replace('\xa0', '') for i in info]
        # print(info)
        info1 = info[1].split('/')
        movie_time = info1[0]
        movie_area = info1[-2]
        movie_type = info1[-1]

        print({
            'movie_name': movie_name,
            'movie_score': movie_score,
            'movie_time': movie_time,
            'movie_area': movie_area,
            'movie_type': movie_type,
        })

if __name__ == '__main__':
    for page in range(1, 11):
        get_data(page)

(四)数据保存(csv)

csv文件格式是一种通用的电子表格和数据库导入导出格式。最近我调用RPC处理服务器数据时,经常需要将数据做个存档便使用了这一方便的格式。

这边主要用的是csv中的字典写入来实现数据持久化的

#创建一个csv
f = open(‘豆瓣top250.csv’, mode=‘w’, encoding=‘utf-8’, newline=‘’)
#表头形式构建
csv_write = csv.DictWriter(f, [
‘movie_name’,
‘movie_score’,
‘movie_time’,
‘movie_area’,
‘movie_type’,
])
#写入表头
csv_write.writeheader()
dic = {‘movie_name’: ‘二十二’, ‘movie_score’: ‘8.7’, ‘movie_time’: ‘2015’, ‘movie_area’: ‘中国大陆’, ‘movie_type’: ‘纪录片’}
#csv字典写入数据
csv_write.writerow(dic)
#关闭csv
f.close()

接着上述实现了解析语法的案例

import csv
import requests
import parsel

def get_data(page,csv_write):
    print(f'==============正在抓取{page}页===================')
    headers = {
        "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,en-GB;q=0.6",
        "cache-control": "max-age=0",
        "priority": "u=0, i",
        "sec-ch-ua": "\"Microsoft Edge\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"Windows\"",
        "sec-fetch-dest": "document",
        "sec-fetch-mode": "navigate",
        "sec-fetch-site": "same-origin",
        "sec-fetch-user": "?1",
        "upgrade-insecure-requests": "1",
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0"
    }

    url = "https://movie.douban.com/top250"
    params = {
        "start": f"{(page-1)*25}",
        "filter": ""
    }
    response = requests.get(url, headers=headers, params=params)

    parsel_text = parsel.Selector(response.text)
    lis = parsel_text.css('.grid_view li')


    for li in lis:
        movie_name = li.css('.title:nth-child(1)::text').get() #标题
        movie_score = li.css('.star .rating_num::text').get() #评分
        info = li.css('.bd>p::text').getall()
        info = [i.strip().replace('\xa0','') for i in info]
        info1 = info[1].split('/')
        movie_time = info1[0]
        movie_area = info1[-2]
        movie_type = info1[-1]

        print({
           'movie_name' :movie_name,
           'movie_score' :movie_score,
           'movie_time' :movie_time,
           'movie_area' :movie_area,
           'movie_type' :movie_type,
        })
        csv_write.writerow({
           'movie_name' :movie_name,
           'movie_score' :movie_score,
           'movie_time' :movie_time,
           'movie_area' :movie_area,
           'movie_type' :movie_type,
        })

if __name__ == '__main__':
    f = open('豆瓣top250.csv', mode='w', encoding='utf-8', newline='')
    csv_write = csv.DictWriter(f, [
        'movie_name',
        'movie_score',
        'movie_time',
        'movie_area',
        'movie_type',

    ])
    csv_write.writeheader()
    for page in range(1,11):
        get_data(page,csv_write)

    f.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值