《Python入门+Python爬虫》——4Day 网络爬虫入门——urllib库的使用 正则表达式

Python学习版本: Python 3.X
观看:Python入门+Python爬虫+Python数据分析
请添加图片描述

1.任务介绍

在这里插入图片描述

2.爬虫初识

在这里插入图片描述
网络爬虫(网络蜘蛛)原理图:
在这里插入图片描述
搜索引擎原理图
在这里插入图片描述

3.基本流程

在这里插入图片描述

3.1准备工作

在这里插入图片描述

3.1.1 分析页面

在这里插入图片描述

3.1.2 编码规范

在这里插入图片描述

if __name__ =="__main__" :   #当前程序执行时,作为程序入口,控制函数执行顺序,
3.1.3 引入模块

在这里插入图片描述

模块 module:一般情况下,是一个以.py为后缀的文件。

  • module 可看作一个工具类,可共用或者隐藏代码细节,将相关代码放置在一个module以便让代码更好用、易懂,让coder重点放在高层逻辑上。

  • module能定义函数、类、变量,也能包含可执行的代码。module来源有3种:
    ①Python内置的模块(标准库);
    ②第三方模块;
    ③自定义模块。

  • 包 package: 为避免模块名冲突,Python引入了按目录组织模块的方法,称之为 包(package)。包是含有Python模块的文件夹。

3.1.4引入库流程

在这里插入图片描述

#常用包
import re   #正则表达式
import urllib.request,urllib.error #制定URL  获取网页数据
import xlwt  #进行excel操作
import bs4  #网页解析 获取数据
import sqlite3 #进行数据库操作

3.2 获取数据

在这里插入图片描述

补充:urllib模块
最最基本的请求
是python内置的一个http请求库,不需要额外的安装。只需要关注请求的链接,参数,提供了强大的解析。

  1. urllb.request 请求模块
  2. urllib.error 异常处理模块
  3. urllib.parse 解析模块

tip: 测试访问网站 http://httpbin.org/

用法讲解
简单的一个get请求

import urllib.request
reponse = urllib.request.urlopen('http://www.baidu.com')
print(reponse.read().decode('utf-8'))

简单的一个post请求

import urllib.request
import urllib.request
#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().decode("utf-8"))

超时处理

import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get',timeout=1)
print(response.read())

import urllib.request
import socket
import urllib.error
try:
	response = urllib.request.urlopen('http://httpbin.org/get',timeout=0.01)
except urllib.error.URLError as e:
	if isinstance(e.reason,socket.timeout):#判断错误原因
		print('time out!')

打印出响应类型,状态码,响应头

import urllib.request
response=urllib.request.urlopen('http://www.baidu.com')
print(type(response))

import urllib.request
response = urllib.request.urlopen('http://www.baidu.com')
print(response.status) # 状态码 判断请求是否成功
print(response.getheaders()) # 响应头 得到的一个元组组成的列表
print(response.getheader('Server')) #得到特定的响应头
print(response.read().decode('utf-8')) #获取响应体的内容,字节流的数据,需要转成utf-8
格式

由于使用urlopen无法传入参数,我们需要解决这个问题
我们需要声明一个request对象,通过这个对象来添加参数

import urllib.request
request = urllib.request.Request('https://python.org') #由于urlopen无法传参数,声明一个Request对象
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8

我们还可以分别创建字符串、字典等等来带入到request对象里面

from urllib import request,parse
url='http://httpbin.org/post'
headers={
	'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
	'Host':'httpbin.org'
}
dict={
	'name':'jay'
}
data = bytes(parse.urlencode(dict),encoding='utf-8')
req=request.Request(url=url,data=data,headers=headers,method='POST')
response=request.urlopen(req)
print(response.read().decode('utf-8'))

我们还可以通过add_header方法不断的向原始的requests对象里不断添加

from urllib import request,parse
url ='http://httpbin.org/post'
dict = {
	'name':'cq'
}
data=bytes(parse.urlencode(dict),encoding='utf-8')
req = request.Request(url=url,data=data,method='POST')
req.add_header('user-agent', 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36')
response=request.urlopen(req)
print(response.read().decode('utf-8')

打印出信息cookies
下面这段程序获取response后声明的cookie对象会被自动赋值

import http.cookiejar,urllib.request
cookie = http.cookiejar.CookieJar()
handerler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handerler)
response=opener.open('http://www.baidu.com') #获取response后cookie会被自动赋值
for item in cookie:
	print(item.name+'='+item.value)

保存cookie文件,两种格式

import http.cookiejar,urllib.request
filename='cookie.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handerler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handerler)
response=opener.open('http://www.baidu.com') #获取response后cookie会被自动赋值
cookie.save(ignore_discard=True,ignore_expires=True) #保存cookie.txt文件
import http.cookiejar,urllib.request
filename='cookie2.txt'
cookie = http.cookiejar.LWPCookieJar(filename)
handerler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handerler)
response=opener.open('http://www.baidu.com') #获取response后cookie会被自动赋值
cookie.save(ignore_discard=True,ignore_expires=True) #保存cookie.txt文件

用文本文件的形式维持登录状态

import http.cookiejar,urllib.request
cookie = http.cookiejar.MozillaCookieJar()
cookie.load('cookie.txt',ignore_discard=True,ignore_expires=True)
handerler=urllib.request.HTTPCookieProcessor(cookie)
opener=urllib.request.build_opener(handerler)
response=opener.open('http://www.baidu.com')
print(response.read().decode('utf-8'))

关于异常处理部分,需要了解有httperror和urlerror两种,父类与子类的关系

#父类,只有一个reason`在这里插入代码片`
from urllib import request,error
try:
	response = request.urlopen('http://www.bai.com/index.html')
except error.URLError as e:
	print(e.reason)
#子类,有更多的属性
from urllib import request,error
try:
	response = request.urlopen('http://abc.123/index.html')
except error.HTTPError as e:
	print(e.reason,e.code,e.headers,sep='\n')

解析,将一个url解析

from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?id=5#comment')
print(result)#协议内容、路径、参数
print(type(result))
from urllib.parse import urlparse
result = urlparse('www.baidu.com/index.html;user?id=5#comment',scheme='https')
print(result)
from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?
id=5#comment',scheme='https')
print(result)
from urllib.parse import urlparse
result = urlparse('http://www.baidu.com/index.html;user?
id=5#comment',allow_fragments=False) #会被拼接
print(result)
from urllib.parse import urlparse
result =
urlparse('http://www.baidu.com/index.html#comment',allow_fragments=False) #会被拼接到path没有query
print(result)
from urllib.parse import urlunparse
data=['http','www.baidu.com','index.html'

url拼接

from urllib.parse import urlunparse
data=['http','www.baidu.com','index.html','user','a=6','comment']
print(urlunparse(data))
from urllib.parse import urljoin
#拼接两个url
#截图,以后面的为基准,有留下,没有拼接
print(urljoin('http://www.baidu.com','HAA.HTML'))
print(urljoin('https://wwww.baidu.com','https://www.baidu.com/index.html;question=2'))
#字典方式直接转换成url参数
from urllib.parse import urlencode
params = {
	'name':'germey',
	'age':'122'
}
base_url='http://www.baidu.com?'
url=base_url+urlencode(params)
print(url)

3.3 解析内容

在这里插入图片描述

3.3.1 标签解析

在这里插入图片描述
补充:BeautifulSoup模块
参考: http://www.jsphp.net/python/show-24-214-1.html

1.BeautifulSoup4简介

BeautifulSoup4和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也
是如何解析和提取 HTML/XML 数据。

BeautifulSoup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐使用lxml 解析器。

Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。

2.BeautifulSoup4主要解析器,以及优缺点:

在这里插入图片描述

3.BeautifulSoup4简单使用

假设有这样一个Html,具体内容如下

<!DOCTYPE html>
<html>
<head>
    <meta content="text/html;charset=utf-8" http-equiv="content-type" />
    <meta content="IE=Edge" http-equiv="X-UA-Compatible" />
    <meta content="always" name="referrer" />
    <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css" />
    <title>百度一下,你就知道 </title>
</head>
<body link="#0000cc">
  <div id="wrapper">
    <div id="head">
        <div class="head_wrapper">
          <div id="u1">
            <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新闻--> </a>
            <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻 </a>
            <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123 </a>
            <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图 </a>
            <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频 </a>
            <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧 </a>
            <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品 </a>
          </div>
        </div>
    </div>
  </div>
</body>
</html>

创建beautifulsoup4对象:

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser") # 缩进格式
print(bs.prettify()) # 获取title标签的所有内容
print(bs.title) # 获取title标签的名称
print(bs.title.name) # 获取title标签的文本内容
print(bs.title.string) # 获取head标签的所有内容
print(bs.head) # 获取第一个div标签中的所有内容
print(bs.div) # 获取第一个div标签的id的值
print(bs.div["id"]) # 获取第一个a标签中的所有内容
print(bs.a) # 获取所有的a标签中的所有内容
print(bs.find_all("a")) # 获取id="u1"
print(bs.find(id="u1")) # 获取所有的a标签,并遍历打印a标签中的href的值
for item in bs.find_all("a"):
	print(item.get("href")) # 获取所有的a标签,并遍历打印a标签的文本值
for item in bs.find_all("a"):
	print(item.get_text())
4.BeautifulSoup4四大对象种类

BeautifulSoup4将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

  • Tag
  • NavigableString
  • BeautifulSoup
  • Comment
Tag

Tag通俗点讲就是HTML中的一个个标签,例如:

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
# 获取title标签的所有内容
print(bs.title)
# 获取head标签的所有内容
print(bs.head)
# 获取第一个a标签的所有内容
print(bs.a)
# 类型
print(type(bs.a))

我们可以利用 soup 加标签名轻松地获取这些标签的内容,这些对象的类型是bs4.element.Tag。但是注意,它查找的是在所有内容中的第一个符合要求的标签。
对于 Tag,它有两个重要的属性,是 name 和 attrs:

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
# [document] #bs 对象本身比较特殊,它的 name 即为 [document]
print(bs.name)
# head #对于其他内部标签,输出的值便为标签本身的名称
print(bs.head.name)
# 在这里,我们把 a 标签的所有属性打印输出了出来,得到的类型是一个字典。
print(bs.a.attrs)
#还可以利用get方法,传入属性的名称,二者是等价的
print(bs.a['class']) # 等价 bs.a.get('class')
# 可以对这些属性和内容等等进行修改
bs.a['class'] = "newClass"
print(bs.a)
# 还可以对这个属性进行删除
del bs.a['class']
print(bs.a)
NavigableString

既然我们已经得到了标签的内容,那么问题来了,我们要想获取标签内部的文字怎么办呢?很简单,用.string 即可,例如

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
print(bs.title.string)
print(type(bs.title.string))
BeautifulSoup

BeautifulSoup对象表示的是一个文档的内容。大部分时候,可以把它当作 Tag 对象,是一个特殊的Tag,我们可以分别获取它的类型,名称,以及属性,例如:

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
print(type(bs.name))
print(bs.name)
print(bs.attrs)
Comment

Comment 对象是一个特殊类型的 NavigableString 对象,其输出的内容不包括注释符号。

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
print(bs.a)
# 此时不能出现空格和换行符,a标签如下:
# <a class="mnav" href="http://news.baidu.com" name="tj_trnews"><!--新闻--></a>
print(bs.a.string) # 新闻
print(type(bs.a.string)) # <class 'bs4.element.Comment'>
5、遍历文档树
5.1 .contents:获取Tag的所有子节点,返回一个list
# tag的.content 属性可以将tag的子节点以列表的方式输出
print(bs.head.contents)
# 用列表索引来获取它的某一个元素
print(bs.head.contents[1])
5.2 .children:获取Tag的所有子节点,返回一个生成器
for child in bs.body.children:
	print(child)
5.3其他方法
方法用法
descendants获取Tag的所有子孙节点
strings如果Tag包含多个字符串,即在子孙节点中有内容,可以用此获取,而后进行遍历
stripped_strings与strings用法一致,只不过可以去除掉那些多余的空白内容
parent获取Tag的父节点
parents递归得到父辈元素的所有节点,返回一个生成器
previous_sibling获取当前Tag的上一个节点,属性通常是字符串或空白,真实结果是当前标签与上一个标签之间的顿号和换行符
next_sibling获取当前Tag的下一个节点,属性通常是字符串或空白,真是结果是当前标签与下一个标签之间的顿号与换行符
previous_siblings获取当前Tag的上面所有的兄弟节点,返回一个生成器
next_siblings获取当前Tag的下面所有的兄弟节点,返回一个生成器
previous_element获取解析过程中上一个被解析的对象(字符串或tag),可能与 previous_sibling相同,但通常是不一样的
next_element获取解析过程中下一个被解析的对象(字符串或tag),可能与next_sibling相同, 但通常是不一样的
previous_elements返回一个生成器,可以向前访问文档的解析内容
next_elements返回一个生成器,可以向后访问文档的解析内容
has_attr判断Tag是否包含属性
6、搜索文档树
6.1、find_all(name, attrs, recursive, text, **kwargs

在上面的例子中我们简单介绍了find_all的使用,接下来介绍一下find_all的更多用法-过滤器。这些过滤器贯穿整个搜索API,过滤器可以被用在tag的name中,节点的属性等。
(1)name参数:
字符串过滤:会查找与字符串完全匹配的内容

a_list = bs.find_all("a")
print(a_list)

正则表达式过滤:如果传入的是正则表达式,那么BeautifulSoup4会通过search()来匹配内容

from bs4 import BeautifulSoup
import re
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
t_list = bs.find_all(re.compile("a"))
for item in t_list:
	print(item)

列表:如果传入一个列表,BeautifulSoup4将会与列表中的任一元素匹配到的节点返回

t_list = bs.find_all(["meta","link"])
for item in t_list:
	print(item)

方法:传入一个方法,根据方法来匹配

from bs4 import BeautifulSoup
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
def name_is_exists(tag):
	return tag.has_attr("name")
t_list = bs.find_all(name_is_exists)
for item in t_list:
	print(item)

(2)kwargs参数:

from bs4 import BeautifulSoup
import re
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html,"html.parser")
# 查询id=head的Tag
t_list = bs.find_all(id="head")
print(t_list)
# 查询href属性包含ss1.bdstatic.com的Tag
t_list = bs.find_all(href=re.compile("http://news.baidu.com"))
print(t_list)
# 查询所有包含class的Tag(注意:class在Python中属于关键字,所以加_以示区别)
t_list = bs.find_all(class_=True)
for item in t_list:
	print(item)

(3)attrs参数:
并不是所有的属性都可以使用上面这种方式进行搜索,比如HTML的data-*属性:

t_list = bs.find_all(data-foo="value")

如果执行这段代码,将会报错。我们可以使用attrs参数,定义一个字典来搜索包含特殊属性的tag:

t_list = bs.find_all(attrs={"data-foo":"value"})
for item in t_list:
	print(item)

(4)text参数:
通过text参数可以搜索文档中的字符串内容,与name参数的可选值一样,text参数接受 字符串,正则表达式,列表

from bs4 import BeautifulSoup
import re
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html, "html.parser")
t_list = bs.find_all(attrs={"data-foo": "value"})
for item in t_list:
	print(item)
t_list = bs.find_all(text="hao123")
for item in t_list:
	print(item)
t_list = bs.find_all(text=["hao123", "地图", "贴吧"])
for item in t_list:
	print(item)
t_list = bs.find_all(text=re.compile("\d"))
for item in t_list:
	print(item)

当我们搜索text中的一些特殊属性时,同样也可以传入一个方法来达到我们的目的:

f length_is_two(text):
	return text and len(text) == 2
t_list = bs.find_all(text=length_is_two)
for item in t_list:
	print(item)

(5)limit参数:
可以传入一个limit参数来限制返回的数量,当搜索出的数据量为5,而设置了limit=2时,此时只会返回前2个数据

from bs4 import BeautifulSoup
import re
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html, "html.parser")
t_list = bs.find_all("a",limit=2)
for item in t_list:
	print(item)

find_all除了上面一些常规的写法,还可以对其进行一些简写:

# 两者是相等的
# t_list = bs.find_all("a") => t_list = bs("a")
t_list = bs("a") # 两者是相等的
# t_list = bs.a.find_all(text="新闻") => t_list = bs.a(text="新闻")
t_list = bs.a(text="新闻")
6.2、find()

find()将返回符合条件的第一个Tag,有时我们只需要或一个Tag时,我们就可以用到find()方法了。当然了,也可以使用find_all()方法,传入一个limit=1,然后再取出第一个值也是可以的,不过未免繁琐。

from bs4 import BeautifulSoup
import re
file = open('./aa.html', 'rb')
html = file.read()
bs = BeautifulSoup(html, "html.parser")
# 返回只有一个结果的列表
t_list = bs.find_all("title",limit=1)
print(t_list)
# 返回唯一值
t = bs.find("title")
print(t)
# 如果没有找到,则返回None
t = bs.find("abc") print(t)

从结果可以看出find_all,尽管传入了limit=1,但是返回值仍然为一个列表,当我们只需要取一个值时,远不如find方法方便。但是如果未搜索到值时,将返回一个None
在上面介绍BeautifulSoup4的时候,我们知道可以通过bs.div来获取第一个div标签,如果我们需要获取第一个div下的第一个div,

t = bs.div.div
# 等价于
t = bs.find("div").find("div")
7.CSS选择器

BeautifulSoup支持发部分的CSS选择器,在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数,即可使用CSS选择器的语法找到Tag
7.1、通过标签名查找

print(bs.select('title'))
print(bs.select('a'))

7.2、通过类名查找

print(bs.select('.mnav'))

7.3、通过id查找

print(bs.select('#u1'))

7.4、组合查找

print(bs.select('div .bri'))

7.5、属性查找

print(bs.select('a[class="bri"]'))
print(bs.select('a[href="http://tieba.baidu.com"]'))

7.6、直接子标签查找

t_list = bs.select("head > title")
print(t_list)

7.7、兄弟节点标签查找

t_list = bs.select(".mnav ~ .bri")
print(t_list)

7.8、获取内容

t_list = bs.select("title")
print(bs.select('title')[0].get_text())
3.3.2 正则提取

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

修饰符描述
re.I使匹配对大小写不敏感
re.L做本地化识别(locale-aware)匹配
re.M多行匹配,影响 ^ 和 $
re.S使 . 匹配包括换行在内的所有字符
re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

re模块下的函数
compile(pattern,string):创建模式对象,string 上面表格的修饰符

import re
pat=re.compile("A")
#m=pat.search("CBA")
m=pat.search("ABC")
#等价于 re.search( A , CBA )
print(m)
#<re.Match object; span=(2, 3), match='A'> 表示匹配到了
m=pat.search("CBD")
print(m) #None 表示没匹配到

search(pattern,string):在字符串中寻找模式

import re
m = re.search("asd" , "ASDasd" )
print(m)
# <_sre.SRE_Match object at 0xb72cd6e8> #匹配到了,返回MatchObject(True)
m = re.search("asd" , "ASDASD" )
print(m) #没有匹配到,返回None(False)

match(pattern,string):在字符串开始处匹配模式

# 等价于
pat=re.compile( "a" )
print(pat.match( "Aasd" ))
#输出None
print(pat.match("aASD" ))
#输出 <_sre.SRE_Match object at 0xb72cd6e8>
# 上面的函数返回都可以在if条件语句中进行判断:
if pat.search("asd"):
	print ("OK") #OK #找到返回
if re.search("a","ASD" ):
	print ("OK") #没有找到

split(pattern,string):根据模式分割字符串,返回列表

re.split( , , a,s,d,asd )
[ a , s , d , asd ] #返回列表
pat = re.compile( , )
pat.split( a,s,d,asd )
[ a , s , d , asd ] #返回列表
re.split( [, ]+ , a , s ,d ,,,,,asd ) #正则匹配:[, ]+,后面说明
[ a , s , d , asd ]
re.split( [, ]+ , a , s ,d ,,,,,asd ,maxsplit=2) # maxsplit 最多分割次数
[ a , s , d ,,,,,asd ]
pat = re.compile( [, ]+ ) #正则匹配:[, ]+,后面说明
pat.split( a , s ,d ,,,,,asd ,maxsplit=2) # maxsplit 最多分割次数
[ a , s , d ,,,,,asd ]

findall(pattern,string):列表形式返回匹配项

import re
print(re.findall( "a" , "ASDaDFGAa" ))
#[ a , a ] #列表形式返回匹配到的字符串
pat = re.compile( "a" )
print(pat.findall( "ASDaDFGAa" ))
#[ a , a ] #列表形式返回匹配到的字符串
pat = re.compile( "[A-Z]+" ) #正则匹配:[A-Z]+ 后面有说明
print(pat.findall( "ASDcDFGAa" ))
#[ ASD , DFGA ] #找到匹配到的字符串
pat = re.compile( [A-Z] )
pat.findall( ASDcDFGAa ) #正则匹配:[A-Z]+ 后面有说明
[ A , S , D , D , F , G , A ] #找到匹配到的字符串
pat = re.compile( [A-Za-z] ) #正则匹配:[A-Za-z]+ 匹配所有单词,后面有说明
pat.findall( ASDcDFGAa )
[ A , S , D , c , D , F , G , A , a ]

sub(pat,repl,string) :用repl替换 pat匹配项
(留的是中间的,因为中间在中心)

re.sub( 'a' , 'A' , 'abcasd' ) #找到a用A替换,后面见和group的配合使用
#AbcAsd
pat = re.compile( 'a' )
pat.sub( 'A' , 'abcasd' )
#AbcAsd
3.3.3 提取数据

在这里插入图片描述
在这里插入图片描述

Day4 豆瓣Top250爬虫

# -*- codeing = utf-8 -*-
import re   #正则表达式
import urllib.request,urllib.error #制定URL  获取网页数据
import xlwt  #进行excel操作
from bs4 import BeautifulSoup #网页解析 获取数据
import sqlite3 #进行数据库操作
def main():
    baseurl="https://movie.douban.com/top250?start="
    datalist = getData(baseurl)
    savepath = ".\\豆瓣电影Top250.xls"
    #saveData(savepath)
    #askUrl("https://movie.douban.com/top250?start=0")

findLink=re.compile(r'<a href="(.*?)">')#创建正则表达式规则, 关键字r 忽略字符串中的转义字符
#影片图片的链接
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)
#爬取网页
def getData(baseurl):
    datalist = []
    for i in range(0,10):
        url = baseurl+str(i*25)
        html = askUrl(url)#保存获取到的网页源码
        #逐一解析
        soup =BeautifulSoup(html,"html.parser")
        for item in soup.find_all('div',class_="item"):    #查找符合要求的字符串 class_ 表示属性
            #print(item) #测试查看电影的iiem
            data =[]    #保存一部电影的所有信息
            item=str(item)
            
            #转化为字符串,使用正则表达式 查找指定的字符串
            #影片详细链接
            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):
                ctitle = titles[0];#添加中文名
                data.append(ctitle)
                otitle =titles[1].replace("/","") #去除无关的符号
                data.append(otitle) #添加外国名
            else:
                data.append(titles[0])
                data.append('  ')#外国名没有时。放空方便存储,
            rating = re.findall(findRating,item)[0]
            data.append(rating) #添加评分
            judegNum = re.findall(findJudge,item)[0]
            data.append(judegNum)   #添加评分人数
            inq=re.findall(findInq,item)
            if len(inq) != 0:
                inq = inq[0].replace("。",'')# 添加概况
                data.append(inq)
            else:
                data.append('  ')
            bd = re.findall(findBd,item)[0]
            bd = re.sub('<br(\s+)?/>(\s+)>'," ",bd)
            bd=re.sub('/'," ",bd)
            data.append(bd.strip())#去除前后空格
            datalist.append(data)

    return  datalist

#指定一个URl的网页内容
def askUrl(url):
    #模拟浏览器头部信息,向豆瓣服务器发送消息
    #用户代理,表示告诉豆瓣服务器我们是什么类型的机器
    head ={
        "User-Agent": "Mozilla/5.0(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0    Safari/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 resulte:
        if hasattr(resulte,"code"):
            print(resulte.code)
        if hasattr(resulte,"reason"):
            print(resulte.reason)

    return html
    
#保存数据
def saveData(savepath):
    print("")
if __name__ =="__main__" :   #当前程序执行时,作为程序入口,控制函数执行顺序,
    main()
    #调用函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值