8月28日第一周
爬虫概念:按照一定规则,自动请求万维网,并获取网页内容
爬虫法律规范:robots君子协议
爬虫限制:非法不允许(密码 明令禁止的)
服务器会做什么:反爬(检查你的信息(修改头部信息);
速度(降低速度);半永久封号(代理ip);验证码)
爬虫的分类:通用爬虫和聚焦爬虫
爬虫为什么选择python语言
爬虫的原理:模拟的正常网站的使用
200 ;404 403 500
浏览器浏览网页的过程:
浏览器通过DNS域名服务器查找对应的ip地址
向ip地址对应的web服务器发送请求
web服务器响应请求,发回html页面
浏览器解析html内容,并显示出来
统一资源定位符url:http://127.0.0.1:8080/subject/python/project.shtml
协议头 服务器地址和端口 文件路径
http和https的区别:SSL
http默认端口80 https默认端口443
ip地址(http://180.97.33.107)—为每一台计算机提供一个编号,非常不容易记忆和理解
所以发明了域名(http://www.baidu.com)代替ip地址
域名和ip地址之间的对应关系表—DNS服务器,完成ip地址和域名之间的映射
域名 ip地址
浏览器显示完整网页的过程:
在浏览器地址栏中输入http://www.baidu.com,
浏览器会发送一个Request请求去获取http://www.baidu.com的HTML页面
服务器会把包含该页面的response对象返回给浏览器
浏览器分析页面中的内容发现其中引用了很多文件,包括image js文件等,所以浏览器会再次发送Request去获取这些图片 js文件、
当所有的文件下载完成,浏览器根据html的语法结构,将网页完整的显示出来
9月4日第二周
1、爬取第一个网页
urllib库:python的内置库
urllib库包括三大模块:urllib.request; urllib.error; urllib.parse
urllib.request:用于请求
urllib.error:处理异常
urllib.parse:用于解析 中文 url编码转换,王%%%
urllib.robotparser:专门解析robots协议
2、爬虫案例
导入库urllib 导入库中的模块request(两种导入方式)
调用库.模块 中的具体函数urlopen—该函数功能打开url地址用的
打开url地址返回response对象,利用.read()函数把对象中的内容读出来
读出来的对象内容为bytes数据类型,利用.decode('utf-8')转码方式把bytes数据类型转化为
国际化编码方式 ,从而保证原格式、中文能正常显示
3、检查你的速度 timesleep休眠时间(后边讲)
服务器是否响应,多久响应,timeout超时,超过此时间服务器不给响应的话,自己终止程序
4、三个小函数:geturl() getcode() info()
5、服务器响应:1、正常响应; 2、是爬虫报红; 3、是爬虫不报红; 4、是爬虫一直等待
区分好三个ruquest:Request请求;request模块,Request函数
为了更好的爬取页面内容,改头换面:更改urse-agent——Request函数,以下为更改步骤:
(1)首先正常访问页面,右击检查,查看网络中Request header信息中的User-Agent,
明确格式为字典值mozilla格式
(2)调用Urllib库中的 request模块中的 Request函数,实现重构头部信息操作
urllib.request.Request(url=url,headers=header)等号左边均为固定格式,等号右边均为单纯的变量名
(3)重构好头部后,再用重构好头部的这个url地址进行发送请求和获取响应
6、urllib库中的parse模块,明确作用——一般用于拼接url地址用:例如让用户输入,完成编码,完成拼接url,进行访问
urllib.parse.urlencode(),此处urlencode函数要求,被编码的对象应为键值对的形式
urllib.parse.quote(),此处quote函数,不要求被编码对象为键值对形式
# import urllib
# from urllib import request
#
# import urllib.request
# resource=urllib.request.urlopen('https://www.baidu.com/') #打开url地址
# # print(resource) #对象
# # resource2=resource.read() #吧对象中的内容读出来
# # print(resource2)
# # resource3=resource2.decode('utf-8')
# # print(resource3)
# print(resource.read().decode('utf-8'))
# import urllib.request
# header={'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 Edg/114.0.1823.67'}
# url='https://www.baidu.com/'
# request1=urllib.request.Request(url=url,headers=header)
# resource=urllib.request.urlopen(request1)
# print(resource.read().decode('utf-8'))
# print(resource.geturl())
# print(resource.getcode())
# print(resource.info())
import urllib.parse
name=input('请你输入要爬取的百度页面,你要爬取谁的百度页面')
data={'wd':name}
result=urllib.parse.urlencode(data)
str='https://www.baidu.com/s?'
print(str+result)
9月11日第三周
1、爬虫分为几步
(1)拼接一下url地址
word=input('请输入要搜索的关键字:')
params=parse.urlencode({'wd':wored})#wd=%%%%%%
url='http://www.baidu.com/s?'.format(params)
header={'User-Agent':'mozi........'}
(2)发送请求获取响应
一、包装请求 二、发送请求 三、获取响应
req=request.Request(url=url,headers=header)
res=request.urlopen(req)
html=res.read().decode('')
(3)保存到本地
一、起名字 filename=word+'.html'
二、执行保存操作
with open(filename,'w') as f:
f.write(html)
1、用户输入—爬取谁的吧
2、转码(urlencode)
3、拼接头部 拼接url地址
4、发送请求 获取响应
5、让用户选择,他想爬取多少页到多少页 就可以爬取(用户输入)
6、找规律,页数page和url地址之间的规律pn=(page-1)*50
7、让page进入for循环
8、结构:类形式(init函数:放一些初始化的函数;get_html发送请求获取响应;
parse_html解析页面提取想要的标题;save_html保存用的,run函数来控制)
程序入口,main
class BaiduTiebaspiader:
def __init__(self):#放一些初始化的函数
pass
def get_html(self):#发送请求获取响应
pass
def parse_html(self):#解析页面提取想要的标题
pass
def save_html(self):#保存用的
pass
def run(self):#控制
pass
if __name__=='__main__':#是否是系统变量,是模块的标识符
spider=BaiduTiebaspiader()
spider.run()
#任意选取符合规定的网站,要求用户输入+爬取(需要涉及转码 拼接url地址 拼接头部)
https://www.baidu.com/s?wd=%E5%88%98%E4%BA%A6%E8%8F%B2
9月18日第四周
import urllib.parse
import urllib.request
#高申
class BaiduTiebaspider:
def __init__(self):#初始化内容
self.url='https://tieba.baidu.com/f?kw={}&pn={}'
self.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 Edg/114.0.1823.67'}
def get_html(self, url):#发送请求获取响应
req=urllib.request.Request(url=url, headers=self.headers)
res=urllib.request.urlopen(req)
html=res.read().decode('utf-8')
return html
def parse_html(self):#解析网页内容
pass
def save_html(self,filename,html):#保存网页内容
with open(filename,'w',encoding='utf-8') as f:
f.write(html)
def run(self):#控制函数的运行
name=input('请你输入贴吧名字:')
start=int(input('请输入起始页:'))
end=int(input('请输入终止页:'))
params=urllib.parse.quote(name)
for page in range(start,end+1):#range前闭后开
pn=(page-1)*50
url=self.url.format(params,pn)
html=self.get_html(url)
filename='{}_第{}页.html'.format(name,page)
self.save_html(filename,html)
if __name__=='__main__':#是否是系统变量,是模块的标识符
spider=BaiduTiebaspider()
spider.run()
9月25日第五周
#数据解析
#要解析的内容分为两类:结构化的 非结构化的
# 非结构化的:办公文档 文本 图像 部分html (先有数据 再有模型)
# 结构化的: xml json(先有模型 再有数据)
#
# 数据解析技术分为以下几种:
# 针对文本的解析:正则表达式
# 针对 HTML或者XML数据解析:xpath、beautifulsoup、正则
# 针对json的解析:jsonpath
import re
title='你好,hello,世界'
pattern=re.compile(r"[\u4e00-\u9fa5]+")#查找中文
result=pattern.findall(title)
print(result)
10月9日第七周
0、介绍课本目录,了解前四周基础知识重要性
明确熟练掌握的知识:爬虫 解析 框架
1、明确任务汇率
安装flask框架 创建汇率文件 创建服务器网站
回顾前4周爬虫知识
书写客户端爬虫代码
2、Get和Post方法
Get 和Post方法在客户端程序写法的区别(重要)
明确GET POST方法的区别:url地址的拼接,安全性;
Get和Post方法在服务器端获取数据的方式完全一致;
Get 和Post方法在路由选择中,默认选择的为get 指定post方式如何指定,两种均可如何指定;
利用Get 和Post方法实现多个参数的设置利用&进行拼接。
3、正则表达式(课本p14页)
10月16日第八周
1、数据解析
针对字符串——正则表达式
针对html xml ——xpath beautifulsoup
针对json——jsonpath
2、正则表达式
import re
r引导“遵循语法”
\d : 匹配数字0-9
b\d+: +多个(最少一次),b开头,匹配多个数字0-9
ab* :*多个(最少0次)
ab? : ?重复?前边的字符(0次或者1次)
a.b :字符a和字符b之间 可以放置任意的字符
ab|ba:满足ab字符可以,满足ba字符也可以
\n占据一个字符位置
空白符占据一个字符位置
\b表示匹配结尾空白位置
[0-9]表示0-9之间的字符任意一个均可
上尖括号出现在[]中的第一个位置,表示对整个[]中的内容取反(不取)
\s表示匹配空格(区别\b,可以表示非结尾 中间位置)
\w:大小写字母 数字均能匹配
上尖括号单独出现,不与[]联合出现,以上尖括号后边的字符作为开头
$表示以$前边的字符作为结尾
3、xpath
(1)xpath语法结构
/ //
. 选取当前节点
.. 选取当前节点的父节点
@属性
[1]第一个
[last()]最后一个
last()-1倒数第二个
position()<3位置的前两个
/a[@lang="title"]
/a[@lang="title"]/b
(2)lxml解析库
目的:
response=urllib.request.urlopen(url)
res=response.read().decode()
print(type(res))
字符串——正则表达式
去字符串
牵涉到的三个类:
Element类——去节点字符串
ElementTree类——去字符串(网页树结构)
ElementPath类——树结构的寻址
(3)Element类——去节点字符串
lxml etree
urllib request
from lxml import etree
root=etree.Element('root')
print(root)
print(a.tag)#.tag表示获取节点的名称
添加属性1——创建节点 并为该节点添加属性
root=etree.Element('root',intersting='totally')
print(root)
print(type(etree.tostring(root)))
添加属性2——在原有节点基础之上 添加节点属性
root.set('age','30')
print(root)
print(etree.tostring(root))
(4)小函数-text()
root=etree.Element('root')
root.text='hello world'
print(root.text)
print(etree.tostring(root))
(5)
ElementTree类——去字符串(网页树结构)
三个函数:
fromstring()-从字符串中解析XML文档,返回根节点
XML()-从字符串中解析XML文档,返回根节点
HTML()-从字符串中解析HTML文档,返回根节点-自动加html body节点
(6)
ElementPath类——树结构的寻址
find()方法
root=etree.XML('<root><a x='123'>xtext</a></root>')
print(root.find('a').tag)
print(root.findall(".//a[@x]")[0].tag)
.urlopen()——response对象
.read()——读操作,bytes数据类型(节点)
.decode()——转码,格式保留 中文正常显示(字符串)
ElementTree类——去字符串(网页树结构)
ElementPath类——树结构的寻址
from lxml import etree root=etree.Element('root') print(etree) print(root.tag) #.tag表示获取节点的名称 etree.Element('root',intersting='totally') print(etree.tostring(root)) #添加属性1——————创建节点 并为该节点添加属性 # etree.Element('root',intersting='totally') # print(root) # print(type(etree.tostring(root))) #添加属性2————在原有节点基础之上添加节点属性 root.set('age','30') print(root) print(etree.tostring(root)) #小函数-text() root=etree.Element('root') root.text='hello world' print(root.text) print(etree.tostring(root)) #ElementTree类————去字符串(网页树结构) # 三个函数: # fromstring()--从字符串中解析XML文档,返回根节点 # XML()———从字符串解析XML文档,返回根节点 # HTML()————从字符串解析HTML文档,返回根节点 xml_data='<root>data</root>' #fromstring()方法 root_one=etree.fromstring(xml_data) print(root_one.tag) print(etree.tostring(root_one)) #XML方法,与fromstring方法基本一样 root_two=etree.XML(xml_data) print(root_two.tag) print(etree.tostring(root_two)) #HTML()方法,如果没有<html>和<body>标签,会自动补上 root_three=etree.HTML(xml_data) print(root_three.tag) print(etree.tostring(root_three)) #ElementPath类————树结构的寻址 #find方法 root=etree.XML('<root><a x='123'>xtext</a></root>') print(root.find('a').tag) print(root.findall(".//a[@x]")[0].tag)
11月6日第十二周
#beautifulsoup和xpath很多一样,设计的目的解析xml html
#字符串——正则 html xml——xpath beautifulsoup json——jsopath
#直接拿过来就可以用
#一、完成buautifulsoup4安装
# 两种方法 安装buautifulsoup4:
# 命令方式 安装: pip3 install beautifulsoup4
# pycharm环境形式 安装:file settings project + beautifulsoup4 安装 ok
#二、导入buautifulsoup类
# from bs4 import BeautifulSoup
#三、传入初始化参数
# soup=BeautifulSoup('html_doc','lxml')
# html_doc被解析的对象 lxml解析器进行解析
#xpath lxml库 解析器
#beautifulsoup lxml库 解析器;python标准库;html5lib解析器
#四、实例
# from bs4 import BeautifulSoup
# markup='<a href="http://example.com" rel="external nonfollow" rel="external nonfollow" rel="external nonfollow">l ike to <i>example.com</i></a>'
# soup=BeautifulSoup(markup,'lxml')
# # print(soup)
# # print(soup.prettify())
# print(soup.find_all('i'))
# print(soup.find_all('i','a'))
# print(soup.find_all(['i','a']))
# print(soup.find_all(rel="external nonfollow"))
#json模块——键值对
#jsonpath寻址——多层嵌套字典 直接进行数据提取
# data={'key1':{'key2':{'key3':{'key4':{'key5':{'key6':'python'}}}}}}
# print(data['key1']['key2']['key3']['key4']['key5']['key6'])
#
# import jsonpath
# print(jsonpath.jsonpath(data,'$.key1.key2.key3.key4.key5.key6'))
# print(jsonpath.jsonpath(data,'$..key6'))
#json模块去字符串 加字符串
# import json
# json.dump()
# json.loads()
# 序列化:python转成字符串 (操作完 执行保存操作前 序列化) json.dump() json.dumps()
# 反序列化:把字符串转成python(寻址之前 对字符串 进行去字符串的操作) json.loads() json.load()
#json.loads的用法
# import json
# str_list='[1,2,3,4]'
# str_dict='{"city":"北京","name":"小明"}'
# print(type(str_list))
# print(type(str_dict))
# print(type(json.loads(str_list)))
# print(type(json.loads(str_dict)))
#json.dump的用法
# import json
# app_list=[
# {"name":"腾讯qq","link":"http://www.qq.com"},
# {"name":"新浪微博","link":"http://www.xinlang.com"},
# {"name":"吃鸡","link":"http://www.***.com"}
# ]
# with open('app.json','w',encoding='utf-8') as f:
# json.dump(app_list,f,ensure_ascii=False)
爬虫
- 最基础的爬虫
Urllib库 .request()模块 .urlopen()
Import urllib.request
Res=Urllib.request.urlopen(url地址)
Res.read().decode()
- 强化版
Urllib库 .request()模块 .parse()模块
.Request() .urlopen()
.urlencode() .parse()
Import urllib.request
Name=Input(“提示用户输入关键词”)
kw=urllib.parse.urlencode(Name)/parse(Name)
Url=’www.baidu.com...’+kw
New_url=Urllib.request.Request(url=url,headers=headers)
res=Urllib.request.urlopen(new_url)
res.read().decode()
- 最终强化
百度贴吧(当前页的爬取:用户的输入 头部信息的拼接 爬取)
Init get_data() parse_data() save_data() run()
对爬虫爬取的东西进行解析
针对不同的网页数据结构有不同的数据解析办法
- 正则表达式——字符串解析(“hsdfhasijchniasfjc”)
Import re
Re.find(“chn”)
- xpath——HTML XML(“<html><body><a><b><c><d>”)
去掉字符串:.fromstring .XML .HTML
寻址:.xpath(xpath寻址规则/ // @ )
百度贴吧(
一、当前页的爬取
二、
当前页的解析—当前页的标题和标题对应的url地址
当前页的解析—下一页的url地址
三、
当前页的标题和标题对应的url地址——保存
下一页的url地址——继续爬取
- 程序终止条件:没有下一页url地址 try except)
3、beautifulsoup——HTML XML(“<html><body><a><b><c><d>”)
安装bs4 导入类from bs4 import Beautifulsoup
初始化Beautifulsoup(被寻址的对象,’lxml’) find寻址
4、json与jsonpath——json(“{body:{a:{b:{c:}}}}”)
导入json模块 调用json.loads()去掉字符串外衣
Jsonpath.jsonpath(被寻址的对象,“$..寻址规则”)
11月20日
安装scrapy框架
1、创建项目 scrapy startproject 项目名字
2、cd到项目下边
创建爬虫 scrapy genspider 爬虫名字 爬虫域名
3、修改settings当中ROBOTSTXT_OBEY=****
4、修改爬虫文件中的parse()模块,完成数据的解析提取
item={}
item['title']=response.xpath('xpath的语法规则')
print(item)#这个print'语句用来测试是否到了第六步,不具有最终的功能
5、程序运行:scrapy crawl 爬虫名字
6、在爬虫文件中输入yield item 把item中的内容yield回管道
7、在管道文件pipelines.py 中,增加print()语句来验证是否数据 真正的放到管道中
8、程序并没有结果输出,所以需要修改settings文件 把item_pipeline释放注释,让其真正有效
9、结果输出没结构,LOG_LEVEL='WARNING'设置输出内容为警告及以上