python-爬虫(最后附爬取数据的源码)

本文介绍了Python网络爬虫的基础知识,包括使用urllib和BeautifulSoup库获取和解析网页数据。通过示例展示了如何处理HTTP请求、设置超时、模拟浏览器访问、解析HTML以及正则表达式的应用。此外,还探讨了数据存储到Excel的方法,为初学者提供了一个全面的爬虫入门教程。
摘要由CSDN通过智能技术生成

爬虫初识

什么是爬虫?

  1. 网络爬虫,是一种按照一定规则,自动抓取互联网信息的程序或者脚本。由于互联网数据的多样性和资源的有限性,根据用户需求定向抓取相关网页并分析已成为如今主流的爬取策略。
  2. 只要能通过浏览器访问的数据都可以通过爬虫抓取。
  3. 爬虫的本质:模拟浏览器打开网页,获取网页中我们想要的那部分数据。

1. 获取数据

python一般使用urllib2获取页面数据

import urllib.request

# 获取一个get请求
response = urllib.request.urlopen("https://www.baidu.com/")
print(response.read().decode("utf-8") # 获取到的网页资源进行utf-8解码

# 获取一个post请求
import urllib.parse
data = bytes(urllib.parse.urlencode({"hello":"world"},encoding = "utf-8"))
response = urllib.request.urlopen("http://httpbin.org/post",data = data)
print(response.read())


# 超时处理
try:
   response = urllib.request.urlopen("http://httpbin.org/get",timeout=0.01)
   print(response.read().decode("utf-8"))
except urllib.error.URLError as e:
   print("time out!")

# 获取请求状态
response = urllib.request.urlopen("https://www.baidu.com/")
print(response.status())

# 将代理更改为模拟浏览器访问
 head = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
        # 模拟浏览器头部信息
    }
    request = urllib.request.Request(url, headers=head)

2. 解析数据

通过导入from bs4 import BeautifulSoup

from  bs4 import  BeautifulSoup

# 打开html文件(可以自定义,但一般都是抓取的页面信息进行解析)
file = open("./文件名.html")
html = file.read()
# 通过html.parser 解析器解析网页数据,给到bs对象
bs = BeautifulSoup(html,"html.parser")
# bs对象存储网页标签元素及其内容(之能拿到找到的第一个内容),以下打印的是title标签中包含的内容 1.Tag 标签及其内容
print(bs.title)

# .string帮助拿到标签中的内容 2.通过type(bs.title.string),得到类型为NavigableString
print(bs.title.string)

# .attrs拿到该标签下的所有属性,并以键值对(字典)的方式表示
print(bs.a.attrs)

# 3.BeautifulSoup类型,拿到网页所有元素
print(bs)

# 4.Comment  是一个特殊的NavigableString 输出内容不包含注释符号

2.1 遍历文档树

  1. .contents :获取Tag的所有子节点,返回一个list
# tag的.content 属性可以将tag的子节点以列表的方式输出
print(bs.head.content)
# 用列表索引来获取它的某一个元素
print(bs.head.content[1])

  1. children : 获取tag所有子节点返回一个生成器
for child in bs.body.children:
    print(child)

2.2文档搜索

# 1.find_all() 
# 通过find_all()方法找到所有的a标签:字符串过滤,会查找到与字符串完全匹配的内容
t_list = bs.find_all(a)
print(t_list)


# 正则表达式搜索,使用search()方法来匹配内容
t_list = bs.find_all(re.compile("a")) # 查询到列表标签包含a字符串的内容
print(t_list)



# 方法:传入一个函数(方法),根据函数的要求来搜索
def name_is_exists(tag):
    return tag.has_attr("name") #找到元素包含name属性的标签
t_list = bs.find_all(name_is_exists)
print(t_list)



# 2. Kwargs 参数:指定参数进行搜索
t_list = bs.find_all(id="head") # 查询属性id 等于head 的内容

t_list = bs.find_all(class_=True) # 打印标签包含class属性的内容


# 3. text 参数
t_list= bs.find_all(text="hao123")  #打印结果为 hao123

t_list= bs.find_all(text= re.compile("/d")) # 通过正则表达式打印出所有文本内容带数字的内容

# 4.limit 参数 控制输出的个数
t_list= bs.find_all("a",limit=3) # 找到html中前三个带a标签的内容


# 5.css选择器
t_list= bs.select('title')  # 通过标签来查找
t_list= bs.select('.类名')  # 通过类名
t_list= bs.select('id') # 通过id
t_list= bs.select("a[class = 名字]") # 查找a标签中 class= 名字 的内容
t_list= bs.select("head > title") # 找到父标签head下的子标签 title

t_list= bs.select(".类名1 ~ .类名2") # 找到.类名1 的兄弟标签.类名2
# 打印兄弟标签的内容
print(t_list[0].get_test())

# 通过for循环打印出来的内容更易阅读
for item in t_list:
    print(t_list)
    

2.3 正则表达式

通用,且常用的正则表达式

操作符说明实例
.表示任何单个字符
[ ]字符集,对单个字符给出取值范围[abc] 表示a、b、c,[a-z]表示a到z单个字符
[^ ]非字符集,对单个字符u给出排除范围[^abc] 非a或b或c的单个字符
*前一个字符0次或无限次扩展abc* 表示 ab、abc、abcc、abccc等
+前一个字符1次或无限次扩展abc+ 表示abc、abcc、abccc等
?前一个字符0次或1次扩展abc? 表示ab、abc
左右表达式任意一个abd丨def 表示abc、def
“左闭右开”是指区间不包括左边的内容,但是涵盖右边的内容。
操作符说明实例
{m}扩展前一个字符m次ab{2}c 表示abbc,ab{3}c 表示abbbc
{m,n}扩展前一个字符m至n次(含n)ab{1,2} c 表示abc、abbc
^匹配字符串开头^abc 表示abc且在一个字符串的开头
$匹配字符串结尾abc$ 表示abc且在一个字符串的结尾
( )分组标记,内部只能使用丨操作符(abc)表示abc,(abc丨def)表示abc、def
\d数字,等价于[0-9]
\w单词字符,等价于[A-Za-z0-9]表示A到Z,a到z,数字0到9

Import re
导入的re库的主要功能函数

函数说明
re.search()在字符串中搜索匹配正则表达式的第一个位置,返回match对象
re.match()从一个字符串的开始位置起匹配正则表达式,返回match对像
re.findall()搜索字符串,以列表类型返回全部能匹配的子串
re.split()将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
re.finditer()搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
re.sub()在一个字符串中替换所有匹配正则表达式的字串,返回替换后的字符串

3. 数据存储

3.1 数据存储–excel

import xlwt
# 创建workbook 对象
workbook = xlwt.Workbook(encoding="utf-8")

# 创建工作表
worksheet = workbook.add_sheet('sheet1')
# 例: 存入九九乘法表
for i in range(1, 10):
    for j in range(1, i+1):
        worksheet.write(i-1, j-1, "%d * %d = %d" % (i, j, i*j))
# 保存数据表
workbook.save('student.xls')

3.2 数据存储–SQLite

(后期补上)

4. 交流学习

5. 爬取源码

from bs4 import BeautifulSoup  # 网页解析,获取数据
import re  # 正则表达式,进行文字匹配
import urllib.request, urllib.error  # 指定URL, 获取网页数据
import xlwt  # 进行excel操作
import sqlite3  # 进行SQLite进行数据库的操作


def main():
    # 获取网页链接
    base_url = "https://movie.***(某电影网站).com/top250?start="
    # 1.爬取网页
    datalist = getData(base_url)

    savePath = "某电影电影top250.xls"
    # 3.保存数据
    saveData(savePath, datalist)


# 创建正则表达式对象,表示规则(字符串模式)
# 影片详情链接规则
findLink = re.compile(r'<a href="(.*?)">') 
# 影片图片
findImgSrc = re.compile(r'<img.*src="(.*?)"/>', re.S)  # re.S 让换行符包含在字符中
# 影片片名
findTitle = re.compile(r'<span class="title">(.*)</span>')
# 影片评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
# 评价人数
findJudge = re.compile(r'<span>(\d*)人评价</span>')
# 概况
findInq = re.compile(r'<span class="inq">(.*)</span>')
# 找到影片的相关内容
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)


# 1.爬取网页
def getData(base_url):
    datalist = []
    for i in range(0, 10):  # 调用获取页面信息的函数10次
        url = base_url + str(i * 25)  # 为参数start赋值
        html = askURL(url)  # 获取到的一页html,返回给到html对象

        # 2.逐一解析数据(在爬取页面时就直接解析,而不是爬取所有在解析)
        # 解析器:html.parser 解析html
        soup = BeautifulSoup(html, "html.parser")
        # 查找网页所有的内容,取标签为div 属性为item的div
        for item in soup.find_all("div", class_="item"):
            data = []  # 保存一部电影的所有信息
            item = str(item)  # 转成字符串

            # 比较规则为findLink 从item里面找出符合findlink规则的内容取第一个符合条件的
            link = re.findall(findLink, item)[0]  # 获取影片链接
            data.append(link)  # 将链接添加到数组中

            # 添加图片
            imgSrc = re.findall(findImgSrc, item)[0]
            data.append(imgSrc)

            # 片名存在中文名,或者中文加外文名
            titles = re.findall(findTitle, item)
            if len(titles) == 2:
                # 添加中文名
                chinese_title = titles[0]
                data.append(chinese_title)
                # 添加外文名  .replace("/", "") 将字符/ 用空值代替
                foreign_title = titles[1].replace("/", "")
                data.append(foreign_title)
            else:
                data.append(titles[0])
                data.append(' ')  # 没有外国名字时 外国名字留空

            # 评分
            rating = re.findall(findRating, item)[0]
            data.append(rating)

            # 评价人数
            judgeNum = re.findall(findJudge, item)[0]
            data.append(judgeNum)

            # 概况
            inq = re.findall(findInq, item)
            if len(inq) != 0:
                inq1 = inq[0].replace("。", "")
                data.append(inq1)
            else:
                data.append(' ')

            # 电影相关内容
            bd = re.findall(findBd, item)[0]
            # 将bd 对象中的<br>标签
            bd = re.sub(r'<br(\s+)?/>(\s+)?', "", bd)
            # 替换\
            bd = re.sub('/', " ", bd)
            # 去掉前后空格
            data.append(bd.strip())
            datalist.append(data)
    print(datalist)
    return datalist


# 3.保存数据
def saveData(savePath, datalist):
    # 创建workbook 对象
    book = xlwt.Workbook(encoding="utf-8", style_compression=0)

    # 创建工作表
    sheet = book.add_sheet('某电影Top250', cell_overwrite_ok=True)
    col = ("电影链接", "图片链接", "影片中文名", "影片外文名", "评分", "评价数", "概况", "相关信息")
    for i in range(0, 8):
        sheet.write(0, i, col[i])  # 写入列名
    for i in range(0, 250):
        print("第%d条" % (i+1))
        # 取datalist中的第i条数据存入data对象
        data = datalist[i]
        for j in range(0, 8):
            # 将data中的第一条数据 存成8列
            sheet.write(i+1, j, data[j])

    # 保存数据表
    book.save(savePath)


# 得到一个指定URL的网页内容(一共250 条,需要爬取25个页面)
def askURL(url):
    # User - Agent 告诉豆瓣服务器,我们是什么类型的机器
    head = {
        "User-Agent": "Mozilla/ 5.0(Windows NT 10.0;Win64; x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 96.0.4664.93Safari / 537.36"
        # 模拟浏览器头部信息
    }
    request = urllib.request.Request(url, headers=head)
    html = ""
    try:
        response = urllib.request.urlopen(request)
        html = response.read().decode("utf-8")
        # print(html)
    except urllib.error.URLError as e:
        if hasattr(e, "code"):
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
    return html


if __name__ == '__main__':
    main()
    print("爬取完毕")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值