Python学习四(爬虫入门、概述、基本流程、BeautifulSoup、re模块)

Python学习

爬虫

一、概述

爬虫就是一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。

二、架构

  1. 调度器:相当于一台电脑的CPU,主要负责调度URL管理器、下载器、解析器之间的协调工作。
  2. URL管理器:包括待爬取的URL地址和已爬取的URL地址,防止重复抓取URL和循环抓取URL,实现URL管理器主要用三种方式,通过内存、数据库、缓存数据库来实现。
  3. 网页下载器:通过传入一个URL地址来下载网页,将网页转换成一个字符串,网页下载器有urllib2(Python官方基础模块)包括需要登录、代理、和cookie,requests(第三方包)
  4. 网页解析器:将一个网页字符串进行解析,可以按照我们的要求来提取出我们有用的信息,也可以根据DOM树的解析方式来解析。网页解析器有正则表达式(直观,将网页转成字符串通过模糊匹配的方式来提取有价值的信息,当文档比较复杂的时候,该方法提取数据的时候就会非常的困难)、html.parser(Python自带的)、beautifulsoup(第三方插件,可以使用Python自带的html.parser进行解析,也可以使用lxml进行解析,相对于其他几种来说要强大一些)、lxml(第三方插件,可以解析 xml 和 HTML),html.parser 和 beautifulsoup 以及 lxml 都是以 DOM 树的方式进行解析的。
  5. 应用程序:就是从网页中提取的有用数据组成的一个应用。

在这里插入图片描述

三、基本流程

1. 准备工作
  1. 通过浏览器的开发者工具分析网页,在Elements下找到需要的数据位置;

  2. 引入和网页爬虫相关的模块

bs4:bs4是一个可以从HTML或XML文件中提取数据的Python库.
xlwt:进行excel操作
re:re 模块使 Python 语言拥有全部的正则表达式功能
urllib:urllib是python内置的HTTP请求库
sqlite3:进行sqlite数据库操作

下载bs4模块:

在这里插入图片描述
下载xlwt模块:

在这里插入图片描述

2. 获取数据(urllib)

一般使用 urllib 库获取页面数据,它是python内置的HTTP请求库,无需安装即可使用,它包含了4个模块:

  • request:它是最基本的http请求模块,用来模拟发送请求;
  • error:异常处理模块,如果出现错误可以捕获这些异常;
  • parse:一个工具模块,提供了许多URL处理方法,如:拆分、解析、合并等;
  • robotparser:主要用来识别网站的robots.txt文件,然后判断哪些网站可以爬。
  1. 获取get请求

示例一:

import urllib.request

class GetHtml(object):
    def __init__(self,URL):
        self.url = URL

    def get_index_get(self):
        self.response = urllib.request.urlopen(self.url)
        return self.response.read()

test_html = GetHtml("http://www.baidu.com")

print(test_html.get_index_get())

运行结果:

在这里插入图片描述
使用utf-8解码:

response.read().decode('utf-8')

运行结果:百度的网页源代码

在这里插入图片描述

示例二:get请求的超时处理

import urllib.request

class GetHtml(object):

    def __init__(self,URL):
        self.url = URL

    def get_index_getTimeout(self):
        try:
            self.response = urllib.request.urlopen(self.url,timeout=0.01)
            print(self.response.read().decode("utf-8"))
        except urllib.error.URLError as e:
            print("Time Out!")


test_html = GetHtml("http://httpbin.org/get")
print(test_html.get_index_getTimeout())

运行结果:

在这里插入图片描述
示例三:

# 获取get请求
import urllib.request

class GetHtml(object):

    def __init__(self,URL):
        self.url = URL

    def get_index_get(self):
        self.response = urllib.request.urlopen(self.url)
        return self.response.read().decode('utf-8')

    def get_index_post(self):
        data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding="utf-8")
        self.response = urllib.request.urlopen(self.url,data= data)
        return self.response.read().decode('utf-8')

    def get_index_getTimeout(self):
        try:
            self.response = urllib.request.urlopen(self.url,timeout=0.01)
            print(self.response.read().decode("utf-8"))
        except urllib.error.URLError as e:
            print("Time Out!")

    def get_index(self):
        self.response = urllib.request.urlopen(self.url)
        # return self.response.status     获取状态码
        return self.response.getheaders() # 获取response headers信息
        # return self.response.getheaders("具体的信息")
test_html = GetHtml("http://www.baidu.com")
print(test_html.get_index())

示例四:使用urllib.request.Request封装

import urllib.request

response = urllib.request.urlopen("http://www.douban.com")
print(response.read().decode("utf-8"))
# 运行结果:418错误,urllib.error.HTTPError: HTTP Error 418:
# 原因该网站对python请求的方式做限制 

修改User-Agent,封装url和header:

url="http://www.douban.com"
headers = {
"User-Agent": Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
}
req = urllib.request.Request(url=url,headers=headers)
response = urllib.request.open(url)
print(response.read().decode("utf-8"))

运行结果:可以获取

在这里插入图片描述

  1. 获取post请求
    httpbin.org 这个网站能测试 HTTP 请求和响应的各种信息,比如 cookie、ip、headers 和登录验证等,且支持 GET、POST 等多种方法。
    post方式必须传递一些表单信息。
import urllib.request

class GetHtml(object):

    def __init__(self,URL):
        self.url = URL

    def get_index_post(self):
        data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding="utf-8")
        self.response = urllib.request.urlopen(self.url,data= data)
        return self.response.read().decode('utf-8')

test_html = GetHtml("http://httpbin.org/post")

print(test_html.get_index_post())

urllib.parse.urlencode里面可以传递用户名密码、cookie等。

运行结果:

在这里插入图片描述

3. 解析内容(BeautifulSoup)
  1. 标签解析:
    使用BeautifulSoup定位特定的标签位置。

BeautifulSoup模块的使用:

# 1. 导入BeautifulSoup库
from bs4 import BeautifulSoup

# 2. 解析内容
soup = BeautifulSoup(html_doc)

# 3. 浏览数据
soup.title         # 获取包含title标签的title
soup.title.string  # 获取title的内容

# 4. 正则使用
soup.find_all(name='x', attrs={'xx':re.compile('xxx')})
  1. 正则提取:
    用来检索、替换某些符合规则的文本,python中使用re模块操作正则表达式。

示例:爬取豆瓣的电影链接

1)从开发者工具查找标签信息

在这里插入图片描述
2)定义搜索链接定义规则,先将所有的div的class="item"过滤出来

from bs4 import BeautifulSoup
# 获取get请求
import urllib.request

url="https://movie.douban.com/top250"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
req = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(req)
# 使用html.parser解析器
soup = BeautifulSoup(response.read().decode('utf-8'),"html.parser")    
# 查找符合要求的字符串,一层一层定义 div 下的 item
for item in soup.find_all('div',class_="item"):
    print(item)

运行结果:

在这里插入图片描述
3)定义规则过滤链接

from bs4 import BeautifulSoup
# 获取get请求
import urllib.request
import re

url="https://movie.douban.com/top250"
# 定义规则
findLink = re.compile(r'<a href="(.*?)">')
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
req = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(req)

# print(response.read().decode('utf-8'))
soup = BeautifulSoup(response.read().decode('utf-8'),"html.parser")

for item in soup.find_all('div',class_="item"):
	# 保存爬取信息
    data = []
    item = str(item)    
    link = re.findall(findLink,item)[0]
    data.append(link)
    print(data)

运行结果:

在这里插入图片描述

4. 保存内容

通过xlwt、sqlite3等模块将爬取的内容保存至excel或数据库中。

四、正则表达式

1. 概述

正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配,re 模块使 Python 语言拥有全部的正则表达式功能。正则语法和之前学习的一样,只不过不同的语言通过不同的工具使用而已。

2. re模块的部分方法
- match和search
# 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
re.match(pattern, string, flags=0)
# 扫描整个字符串并返回第一个成功的匹配
re.search(pattern, string, flags=0)
# 参数:
pattern:匹配的正则表达式
string:要匹配的字符串。
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
  • 注意:re.match()和re.search()区别

re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 re.search 匹配整个字符串,直到找到一个匹配。

- sub

用于替换字符串中的匹配项。

re.sub(pattern, repl, string, count=0, flags=0)
# 参数:
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
- findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

re.findall(pattern, string, flags=0)
  • 注意:
    match 和 search 是匹配一次 findall 匹配所有。
- compile

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

re.compile(pattern,flags)
# 参数
pattern : 一个字符串形式的正则表达式
flags : 可选,表示匹配模式,比如忽略大小写,多行模式等

五、示例

1. 爬取网页课程名称

爬取 ichunqiu 课程名称,抓包分析为POST请求,共有19页,页数由pageIndex变量控制,定制headers并传入data进行爬取:

在这里插入图片描述

import requests
import json
import _thread
import time


def get_lesson_name(data):
    url = "https://www.ichunqiu.com/courses/ajaxCourses"

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

    r = requests.post(url=url, headers=headers, data=data)

    datas = json.loads(r.text)

    name_long = len(datas['course']['result'])

    for i in range(name_long):
        print(datas['course']['result'][i]['courseName'])


if __name__ == '__main__':
    for i in range(1, 20):
        data = {
            'courseTag': '',
            'courseDiffcuty': '',
            'IsExp': '',
            'producerId': '',
            'orderField': '',
            'orderDirection': '',
            'pageIndex': str(i),
            'tagType': '',
            'isOpen': ''
        }
        _thread.start_new_thread(get_lesson_name, (data,))
        time.sleep(0.5)
# python3中使用 _thread模块开启线程:start_new_thread(function, args, kwargs=None)(方法名,参数必须是元组形式)
# 使用_thread不能控制控制线程数,必须加sleep休眠时间

运行结果:

在这里插入图片描述

2. 爬虫下载图片
"""
1. 通过正则表达式匹配所有的图片url
2. 通过for循环将获取的图片url列表存入新的列表并拼接上完整的图片下载url
3. 使用write方法将爬下的完整
"""
# 正则表达式   re模块
import urllib.request
import re

class GetHtml(object):
    def __init__(self,URL,HEADER):
        self.url = URL
        self.header = HEADER

    def get_index(self):
        self.request = urllib.request.Request(self.url)
        self.request.add_header("user-agent",self.header)
        self.response = urllib.request.urlopen(self.url)
        return self.response.read()

    def get_list(self):
        # 定义空列表用来存放图片下载的完整url
        self.string_imglist = []
        # 使用正则表达式匹配所有的图片url
        self.imglist = re.findall("图片的scr的正则表达式.jpg",self.get_index())
        # for循环拼接完整的下载路径
        for i in self.imglist:
            self.string_imglist.append(self.url+str(i,encoding="utf-8"))
            print(self.imglist)
            return self.string_imglist

    def get_image(self):
    	# 下载图片:图片名为从1.jpg递增
        num = 0
        for self.url in self.get_list():
            num += 1
            with open(str(num) + ".jpg","wb") as f:
                f.write(self.get_index())

test_html = GetHtml("网页地址","user-agent具体信息")
test_html.get_image()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值