通用爬虫:
实例
百度、360、google、sougou等搜索引擎‐‐‐伯乐在线
功能
访问网页‐>抓取数据‐>数据存储‐>数据处理‐>提供检索服务
robots协议
一个约定俗成的协议,添加robots.txt文件,来说明本网站哪些内容不可以被抓取,起不到限制作用
自己写的爬虫无需遵守
网站排名(SEO)
1. 根据pagerank算法值进行排名(参考个网站流量、点击率等指标)
2. 百度竞价排名
缺点
1. 抓取的数据大多是无用的
2.不能根据用户的需求来精准获取数据
聚焦爬虫
功能
根据需求,实现爬虫程序,抓取需要的数据
设计思路
1.确定要爬取的url
如何获取url
2.模拟浏览器通过http协议访问url,获取服务器返回的html代码
如何访问
3.解析html字符串(根据一定规则提取需要的数据)
如何解析
反爬虫手段?
1.User-Agent:
User Agetn中文名为用户代理,简称UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统以及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
2.代理IP
西次代理
快代理
什么是高匿名、匿名和透明代理?它们有什么区别?
1.使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP
2.使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP
3.使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP
3.验证码访问
打码平台
云打码平台
超级鹰
4.动态加载网页 网站返回的是js数据 并不是网页的真实数据
selenium驱动真实的浏览器发送请求
5.数据加密
分析js代码
urllib库使用
urllib.request.urlopen() 模拟浏览器向服务器发送请求
response 服务器返回的数据
response的数据类型是HttpResponse
字节–>字符串
解码decode
字符串–>字节
编码encode
read() 字节形式读取二进制 扩展:read(5)返回前几个字节
readline() 读取一行
readlines() 一行一行读取 直至结束
getcode() 获取状态码
geturl() 获取url
getheaders() 获取headers
urllib.request.urlretrieve()
请求网页
请求图片
请求视频
案例:获取百度页面的源码
#使用urlllib获取百度首页的源码
import urllib.request
#(1)定义一个url,就是你要访问的地址
url = ‘https://www.baidu.com/’
#(2)模拟浏览器向服务器发送请求 response 响应
response = urllib.request.urlopen(url)
#(3) 获取响应中的页面的源码 content 内容
#read方法 返回的是字节形式的二进制 b’\r\n\r\n\t
二进制 --》字符串 解码 decode(‘编码格式’)
content = response.read().decode(‘utf-8’)
#(4)打印数据
print(content)
没有解码输出结果如下:(其中b是二进制的意思)
有解码输出如下:
urllib的一个类型和六个方法
import urllib.request
url = ‘http://www.baidu.com’
#模拟浏览器向服务器发送请求
response = urllib.request.urlopen(url)
#一个类型和六个方法
print(type(response)) #<class ‘http.client.HTTPResponse’>
#按照一字节一个字节地去读
content = response.read()
print(content)
#返回多少个字节
content = response.read(5)
print(content) #b’<!DOC’
#按行读,读取一行
content = response.readline()
print(content)
#一行一行读取 直至结束
content = response.readlines()
print(content) #200
#返回状态码,如果是200,那么久证明我们的逻辑没有错
print(response.getcode())
#返回的是url地址
print(response.geturl()) # #http://www.baidu.com
#获取的是一个状态信息
print(response.getheaders())
import urllib.request
#下载网页
url_page= ‘http://www.baidu.com’
#url代表的是下载的路径,filename文件的名字
#在python中 可以变量的名字 也可以直接写值
urllib.request.urlretrieve(url_page,‘baidu.html’)
#下载图片
url_img = ‘https://img0.baidu.com/it/u=2832432234,231987514&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=887’
urllib.request.urlretrieve(url_img, ‘美杜莎.jpg’)
#下载视频
url_video = ‘https://vd4.bdstatic.com/mda-pm16yaekshe85hn1/720p/h264/1701492867652415090/mda-pm16yaekshe85hn1.mp4?v_from_s=hkapp-haokan-hnb&auth_key=1701508956-0-0-992ac895c1ebbe4417e7b0df3cc2db7a&bcevod_channel=searchbox_feed&pd=1&cr=2&cd=0&pt=3&logid=1356498233&vid=23740490631090888&klogid=1356498233&abtest=114240_1-114675_1’
urllib.request.urlretrieve(url_video,‘视频.mp4’)
请求对象的定制
方法:1.百度搜索“ua大全"
2.鼠标右键检查页面(F12),刷新一下页面,查找Headers,然后在里面找到自己的ua
语法:request = urllib.request.Request()
案例:
import urllib.request
url = ‘https://www.baidu.com’
#url组成
#https://www.baidu.com/s?wd=周杰伦
#http/https www.baidu.com 80/443 s wd=周杰伦
协议 主机 端口号 路径 参数 锚点
#http 80
#https 443
#mysql 3306
#oracle 1521
#redis 6379
#mongodb 27017
#如果不伪装,就返回的内容很少,原因右反爬虫机制
headers = {
‘User-Agent’:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36’}
#因为urlopen方法中不能存储字典,所以headers不能传递进去
#请求对象的定制
#注意 因为参数顺序的问题,不能直接写url和headers 中间还有data 所以我们需要关键字传参
request = urllib.request.Request(url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode(‘utf-8’)
print(content)
扩展:编码的由来
urllib.quote方法
#https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&rsv_spt=1
#需求: 获取 https://www.baidu.com/s?wd=周杰伦的网页源码
import urllib.request
url = ‘https://www.baidu.com/s?wd=’
#请求对象的定制为了解决反爬虫的第一种手段
headers = {
‘User-Agent’:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36’
}
#将周杰林三个字变成unicode编码格式
#我们选哟依赖于urllib.parse
name = urllib.parse.quote(‘周杰伦’)
print(name)
url = url + name
#请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
#模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
#获取响应的内容
content = response.read().decode(‘utf-8’)
#打印数据
print(content)
#urlencode应用场景:多个参数的时候
https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7
#https://www.baidu.com/s?wd=周杰林&sex=男
import urllib.parse
data = {
‘wd’:‘周杰伦’,
‘sex’:‘男’,
‘location’:‘中国台湾省’
}
a = urllib.parse.urlencode(data)
print(a)
#获取https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7&location=%E4%B8%AD%E5%9B%BD%E5%8F%B0%E6%B9%BE%E7%9C%81的网页源码
import urllib.request
import urllib.parse
base_url = ‘https://www.baidu.com/s?’
data ={
‘wd’:‘周杰伦’,
‘sex’:‘男’,
‘location’:‘中国台湾省’
}
new_data = urllib.parse.urlencode(data)
url = base_url + new_data
print(url)
#请求对象的定制为了解决反爬虫的第一种手段
headers = {
‘User-Agent’:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36’
}
#请求对象的定制
request = urllib.request.Request(url = url,headers=headers)
#模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
#获取网页源码数据
content = response.read().decode(‘utf-8’)
#打印数据
print(content)
案例:
#post 请求
import urllib.request
import urllib.parse
url = ‘https://fanyi.baidu.com/sug’
#请求对象的定制为了解决反爬虫的第一种手段
headers = {
‘User-Agent’:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36’
}
data = {
‘kw’: ‘spider’
}
#post请求参数 必须进行编码
data = urllib.parse.urlencode(data).encode(‘utf-8’)
#post 请求参数是不会拼接在url的后面的 而是需要放在请求对象定制的参数中
#post 请求的参数,必须进行编码
#请求对象的定制
request = urllib.request.Request(url=url,data=data,headers=headers)
#模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
#获取响应数据
content = response.read().decode(‘utf-8’)
print(content)
#字符串 -->json对象
import json
obj = json.loads(content)
print(obj)
#post 请求方式的参数 必须编码 data = urllib.parse.urlencode(data)
#编码之后 必须调用encode方法 data = urllib.parse.urlencode(data).encode(‘utf-8’)
#参数是放在请求对象定制的方法中 request = urllib.request.Request(url=url,data=data,headers=headers)
案例:爬取百度翻译详细内容
import urllib.request
import urllib.parse
import json
url = ‘https://fanyi.baidu.com/v2transapi?from=en&to=zh’
#请求对象的定制为了解决反爬虫的第一种手段
headers = {
‘Cookie’:‘BIDUPSID=6BC4D39DD5CA78BD05FC00D849CEF42A; PSTM=1676609286; BAIDUID=C9EAFF78F1CD22887F2402CD303A3853:FG=1; MCITY=-119%3A; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; H_WISE_SIDS=234020_216852_213359_214792_110085_244723_261716_236312_265881_266353_267074_259031_268592_268031_259642_269832_269749_269904_270516_271173_265032_266027_270102_271812_271939_234295_234207_272282_267596_272828_260335_273161_273120_273245_273300_273393_271157_273734_263619_273165_263750_274300_274323_272562_274425_274440_274892_267807_267548_273923_275167_275211_272317_275616_275259_275770_275793_275007_275825_275864_275995_275940_275849_275970_276089_269610_276120_276122_276203_276251_274503_276196_276312_276343_275170_276448_272168_276510_276586_276629_275589_276390_276738_275208_276796_276875_276985_276986_276964_276759_253022_268758_277217_270366_277212_277272_274356_277312_276947_277356_277369_277236_251972_277543_274784_271254_273981_277636_277612_8000001_8000087_8000114_8000121_8000138_8000146_8000163_8000166_8000175_8000177_8000176_8000186_8000203; BAIDUID_BFESS=C9EAFF78F1CD22887F2402CD303A3853:FG=1; H_WISE_SIDS_BFESS=234020_216852_213359_214792_110085_244723_261716_236312_265881_266353_267074_259031_268592_268031_259642_269832_269749_269904_270516_271173_265032_266027_270102_271812_271939_234295_234207_272282_267596_272828_260335_273161_273120_273245_273300_273393_271157_273734_263619_273165_263750_274300_274323_272562_274425_274440_274892_267807_267548_273923_275167_275211_272317_275616_275259_275770_275793_275007_275825_275864_275995_275940_275849_275970_276089_269610_276120_276122_276203_276251_274503_276196_276312_276343_275170_276448_272168_276510_276586_276629_275589_276390_276738_275208_276796_276875_276985_276986_276964_276759_253022_268758_277217_270366_277212_277272_274356_277312_276947_277356_277369_277236_251972_277543_274784_271254_273981_277636_277612_8000001_8000087_8000114_8000121_8000138_8000146_8000163_8000166_8000175_8000177_8000176_8000186_8000203; BAIDU_WISE_UID=wapp_1697164414135_388; BDSFRCVID_BFESS=7bDOJeC62uGbXOnqMj5FEHtYogQvyW5TH6aop7BC0VwcZsuRDQnHEG0P_M8g0Ku-TwRVogKK3gOTHxjKo2t2qPqgrfTy57Tm6h-ftf8g0M5; H_BDCLCKID_SF_BFESS=tRCH_CPXJKL3fJrYhPIV-PAt-U4Xat0XKKOLVK3t3p7keq8CDRon-lkghlQuajQl3mbJhR7jL4QBSI52y5jHhnOWL4-jLJb2yj7tbqblaqnpsIJMBUFWbT8U5ecn-hjpaKviaKOjBMb1JbcohT5MDR_rKfJHKq38JRvnWCQSHRQMeCnTDMFhe4tX-NFfJTF83D; BDUSS=nNtTnV5SEJhR3pWVzY1UjdPVkE3clpodHF3eHFHbVZTfjktZHhzMEJVSDc5bzlsRVFBQUFBJCQAAAAAAAAAAAEAAACFoSjqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtpaGX7aWhlS; BDUSS_BFESS=nNtTnV5SEJhR3pWVzY1UjdPVkE3clpodHF3eHFHbVZTfjktZHhzMEJVSDc5bzlsRVFBQUFBJCQAAAAAAAAAAAEAAACFoSjqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPtpaGX7aWhlS; H_PS_PSSID=39676_39713_39738_39779_39703_39680_39679_39817_39834_39784_39840; delPer=1; PSINO=6; BA_HECTOR=2l200h8l8h240kal812g2gai1imlnsk1r; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1701502869; ZFY=yp27t:BPcDOjqPWE1IeOatE93I:AG2cmc2zdBBmo0btrU:C; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1701504253’,
‘Host’:‘fanyi.baidu.com’,
‘Referer’:‘https//fanyi.baidu.com/’,
‘User-Agent’:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0’,
‘X-Requested-With’:‘XMLHttpRequest’
}
data = {
‘from’:’ en’,
‘to’:’ zh’,
‘query’:’ love’,
‘simple_means_flag’:’ 3’,
‘sign’:’ 198772.518981’,
‘token’:’ aed5d3774a92a8afff6f0918da6ae19b’,
‘domain’:’ common’,
‘ts’:’ 1701504253941’
}
#post请求的参数必须进行编码,并且调用encode方法
data = urllib.parse.urlencode(data).encode(‘utf-8’)
#请求对象的定制
request = urllib.request.Request(url=url,data=data,headers=headers)
#模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
#获取响应数据
content = response.read().decode(‘utf-8’)
obj =json.loads(content)
print(obj)
案例:爬取豆瓣电影第一页数据
#get请求
#获取豆瓣电影的第一页的数据 并保存起来
import urllib.request
url = ‘https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20’
#如果不伪装,就返回的内容很少,原因右反爬虫机制
headers = {
‘User-Agent’:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36’}
#(1)请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
#(2)获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode(‘utf-8’)
#(3)数据下载到本地
#open方法默认情况下适用的是gbk编码,如果我们要想保存汉字,那么需要在open方法中指定编码格式为utf-8
#encoding = ‘utf-8’
fp = open(‘douban.json’,‘w’,encoding=‘utf-8’)
fp.write(content)
with open(‘douban1.json’,‘w’,encoding=‘utf-8’) as fp:
fp.write(content)
案例:爬取豆瓣电影前10页数据
https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
start=0&limit=20
https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
start=20&limit=20
https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
start=40&limit=20
import urllib.request
import urllib.parse
#下载豆瓣电影前10页数据
#(1)请求对象定制
#(2)获取响应数据
#(3)下载数据
def create_request(page):
base_url = ‘https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&’
data = {
'start':(page-1)*20 ,
'limit':20
}
data = urllib.parse.urlencode(data)
url = base_url +data
# print(url)
headers= {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
}
request = urllib.request.Request(url=url,headers=headers)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode(‘utf-8’)
return content
def down_load(page,content):
with open(‘douban’+ str(page)+‘.json’,‘w’,encoding=‘utf-8’) as fp:
fp.write(content)
#程序的入口
if name == ‘main’:
start_page = int(input(‘请输入起始的页面’))
end_page = int(input(“请输入结束的页码”))
for page in range(start_page,end_page+1):
# 每一页都有自己的请求对象的定制
request = create_request(page)
#获取响应的数据
content = get_content(request)
#下载
down_load(page,content)
#用crtl +alt + l 看生成的文件
案例:爬取肯德基前10页数
1页
https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
post
cname: 佛山
pid:
pageIndex: 1
pageSize:10
2页
https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
cname: 佛山
pid:
pageIndex: 2
pageSize: 10
import urllib.request
import urllib.parse
base_url = ‘https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname’
def create_request(page):
base_url = ‘https://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname’
data = {
'cname': '佛山',
'pid': '',
'pageIndex': page,
'pageSize': '10'
}
data = urllib.parse.urlencode(data).encode('utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
}
request = urllib.request.Request(url=base_url,headers=headers,data=data)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page, content):
with open(‘kfc_’ + str(page) + ‘.json’, ‘w’, encoding=‘utf-8’) as fp:
fp.write(content)
if name == ‘main’:
start_page = int(input(“请输入起始页码”))
end_page = int(input(“请输入结束页码”))
for page in range(start_page, end_page + 1):
# 请求对象的定制
request = create_request(page)
# 获取网页的源码
content =get_content(request)
# 下载
down_load(page,content)
URLError\HTTPError
案例“
import urllib.request
import urllib.error
url = ‘https://blog.csdn.net/sulixu/article/details/1198189491’
url = ‘http://www.doudan111.com’
headers= {
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36’
}
try:
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
except urllib.error.HTTPError:
print(“系统正在升级…”)
except urllib.error.URLError:
print(“我都说了系统正在升级”)
复制有点问题可以看我的有道云笔记:
https://note.youdao.com/s/AxrLbSnc