爬虫-spider

发布于:2022-11-03 ⋅ 阅读:(364) ⋅ 点赞:(0)

首先需要学习以下基础知识

1.python基础

2.前端页面技术

3.爬虫技术

什么是互联网爬虫

通过一个程序根据URL进行爬取网页,获取有用信息。使用程序模拟浏览器,去想服务器发送请求,获取响应信息。

爬虫核心

抓取网页,解析数据,爬虫和反爬虫之间的博弈(难点)

爬虫的用途

数据分析/人工智能,社交软件冷启动,舆情监控,竞争对手监控

爬虫分类

通用爬虫:实例 百度、360、google等搜索软件

缺点:抓取的数据大多是无用的,不能根据用户的需求精准获取数据

聚集爬虫:功能:根据需求,实现爬虫程序,抓取需要的数据

设计思路:

1.确定需要,获取url,

2.模拟浏览器通过http协议访问url,获取服务器返回的html代码

3.解析html字符串(根据一定规则提取需要的数据)

反爬手段

1.User Agent(用户代理)简称UA,是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU类型,浏览器版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

2.代理IP 如果超出常人的基本操作基本行为,就会封掉IP

3.验证码访问 打码平台

4.动态加载网页 网站返回的是js数据,并不是网页的真实数据

5.数据加密 分析js代码

urllib库使用

urllib.request.urlopen()模拟浏览器向服务器发送请求

需求:#使用urllib获取百度首页的源码

第一步:定义一个URL(要访问的地址)

URL的组成部分:

在后面请求对象的定制中

url='http://www.baidu.com'

第二步:模拟浏览器向服务器发送请求

导入import urllib.request

response=urllib.request.urlopen(url)  当模拟浏览器向服务器发送请求时,服务器会给你一个反馈,需要一个变量接受这个反馈,常用响应response来接收这个反馈。

第三步:获取响应中的页面的源码(不要别的),获取到的内容用content接受

content=response.read()

read()方法:返回的是字节形式的二进制数据(带b),需要将二进制的数据转换成字符串,这个过程叫做解码,方法叫decode('编码的格式')

content=response.read().decode('utf-8')(utf-8对应页面的编码格式)

第四步:打印数据(直到获取的是否有内容)

print(content)

服务器返回的response中不仅仅有页面源码,除了read()获取源码外还有其他方法

一个类型和六个方法

print(type(response))  获取到的类型为:HTTPResponse

response是HTTPResponse的类型

contend=response.read() 读取响应的内容,按照一个字节一个字节的去读

content=response.read(5) 返回了5个字节,代表返回多少个字节

 content=response.readline()  只能读取一行,但是快

content =response.readlines() 一行一行的读,直到读完,还是一个二进制

print(response.getcode())返回状态码,判断代码是否有问题,如果返回200则代码逻辑没有错。

print(response.geturl())  返回的是url地址

print(response.getheaders()) 返回的是响应头(状态信息)

将爬取的东西下载到本地(采集图片,视频等)

可以下载网页,图片,视频

url_page='http:www.baidu.com'

urllib.request.urlretrieve(url,filename)

参数url代表下载的路径,filename文件的名字

可以写url=url_page,'baidu.html' 注意文件后缀很重要

同理图片和视频下载类似

import urllib.request
#下载一个网页

url_page='http://www.baidu.com'
#url代表下载的路径 filename文件的名字
#在python中 可以写变量的名字 也可以直接写值
urllib.request.urlretrieve(url_page,'baidu.html')
#下载图片
url_img='https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi2.hdslb.com%2Fbfs%2Farchive%2Fbe8d5274c6f1c9957e1e5262f3b56e89854e1113.jpg&refer=http%3A%2F%2Fi2.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1669605623&t=8a83fec7e865a1e087c4ac5355ae5e2a.jpg'
urllib.request.urlretrieve(url=url_img,filename='lisa.jpg')
#下载视频
url_video='https://vd2.bdstatic.com/mda-njtfkfkcwnvz04py/sc/cae_h264/1666960923439992738/mda-njtfkfkcwnvz04py.mp4?v_from_s=hkapp-haokan-nanjing&auth_key=1667015621-0-0-7fcec793e09a5b911662bb61552c6195&bcevod_channel=searchbox_feed&cd=0&pd=1&pt=3&logid=1421108170&vid=9049491074114251603&abtest=104959_2-104859_2-105227_2&klogid=1421108170'
urllib.request.urlretrieve(url_video,filename='children.mp4')

urllib请求对象的定制

url='https://www.baidu.com'

url的组成有6部分

http/https(协议)加s的更加安全,www.baidu.com域名也就是主机地址  ,

端口号:http的是80,https的是443,mysql的是3306,  oracle 的是1521 , redis是6379

https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
路径:s
参数:?后面的数据 wd=周杰伦
锚点:#

返回的数据不完整,遇到的第一个反爬是因为给的数据不完整,

网页检查,点击网络network,在标头headers里 获取UA,发现有冒号像字典类型的数据,字典里要有字符串。

源码中显示urlopen的参数并提示

#Open the URL url, which can be either a string or a Request object

这时就需要请求对象的定制:因为urlopen方法中不能存储字典,所以headers不能传入。

伪装成一个整体,因为参数顺序的问题不能直接写url,headers,

需要关键字传参: 

request=urllib.request.Request(url=url,headers=headers)
response= urllib.request.urlopen(request)

编解码

1.get请求方式:urllib.parse.quote()

需求 获取https://www.baidu.com/s?wd=周杰伦

url ='https://www.baidu.com/s?wd='

#要将周杰伦三个字编成unicode编码的格式
#需要依赖于urllib.parse使用quote方法
name = urllib.parse.quote('周杰伦')

url=url+name

#编码集的演变

#需求 获取https://www.baidu.com/s?wd=周杰伦的网页源码
import urllib.request
import urllib.parse
url ='https://www.baidu.com/s?wd='

#请求对象定制--为了解决反爬的第一种手段UA
headers = {
'User-Agent':' '
}
#要将周杰伦三个字编成unicode编码的格式
#需要依赖于urllib.parse使用quote方法
name = urllib.parse.quote('周杰伦')
#print(name)#%E5%91%A8%E6%9D%B0%E4%BC%A6
url=url+name
#print(url)#https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
#请求对象的定制
request=urllib.request.Request(url=url,headers=headers)

#模拟浏览器向服务器发送请求
response= urllib.request.urlopen(request)

#获取响应的内容
content=response.read().decode('utf-8')

#打印数据
print(content)

2.get请求方式:urlencode方法(应用场景就是多个参数时使用)

wd后面用&符号连接了很多参数,需要转为unicode字符,要求参数要以字典的形式存在。

#urlencode应用场景,多个参数的时候使用


#https://www.baidu.com/s?wd=周杰伦&sex=男
'''
import urllib.parse
data ={
    'wd':'周杰伦',
    'sex':'男',
    'location':'中国台湾省',
}
a=urllib.parse.urlencode(data)
#print(a)#wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7
#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

'''
#获取https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7的网页源码
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

#防止做反爬
headers={
    'User-Agent': ''
}
#请求对象的定制
request=urllib.request.Request(url=url,headers=headers)

#模拟浏览器向服务器发请求
response=urllib.request.urlopen(request)
#获取网页源码的数据
content=response.read().decode('utf-8')

#打印数据
print(content)

3.post请求方式:

#post请求的参数 必须要进行编码  编码后必须调用encode方法
data=urllib.parse.urlencode(data).encode('utf-8')

#post的请求参数是不会拼接在url后面,而是需要放在请求对象定制的参数中
#post请求的数据必须进行编码
request=urllib.request.Request(url=url,data=data,headers=headers)

#post请求百度翻译
#post请求
import urllib.request
import urllib.parse
url ='https://fanyi.baidu.com/sug'

headers = {
'User-Agent':''
}

#post请求的参数应该放在哪
data={
    'kw':'spider',
}
#post请求的参数 必须要进行编码  编码后必须调用encode方法
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)

#获取响应的数据
#print(response)#TypeError: POST data should be bytes
content=response.read().decode('utf-8')
#字符串变成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
url='https://fanyi.baidu.com/v2transapi?from=en&to=zh'

#起决定性作用的是cookie,
headers = {
    #'Accept': '*/*',
    #'Accept-Encoding':' gzip, deflate, br', #需要注释掉
    #'Accept-Language': 'zh-CN,zh;q=0.9',
    #'Acs-Token': '1666940606973_1667025165241_wUz+zBfO7j24XvsZbTcRsnibLDg7sS3ASv0TjBc7Wa49hvH49OwhCxx2Ha7pZC8HQEAvi7Z6DR3j2nzOu9VKvktKFfiRa3n971UsV/WrSK11dyeLQbxOkvhPYad7NEd8JDbz/YL4+y97jKIeJieLplG71EK2uZKOgmkWkdp9456MUtoX3136SsoJCCWFTSLnMsAJUrLu4XpFHJWbzS8uq7GsHp3p/2L4wahCAM9s+rmr+lOg8hXhPzmWBA37DT81iPygwWe8/O/j66zF+730Ej+nGEH3bkThwRN6XzVetuMgpzpKgVgur+7A+TihqGNs',
    #'Connection':'keep-alive',
    #'Content-Length': '135',
    #'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie':' BIDUPSID=9111318699517B1BF24BF48B93814A82; PSTM=1623657042; BAIDUID=217613BFEA4B7E9B42ADC0795B1C33DD:FG=1; H_PS_PSSID=26350; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; BAIDUID_BFESS=217613BFEA4B7E9B42ADC0795B1C33DD:FG=1; BA_HECTOR=a10g202hag808h0ha50g1u4i1hlpdbj1b; ZFY=k9XM400WDOObh0TZMyuxNIG2qgk9ngEvUv:BPQXMOMb8:C; BDRCVFR[u-uf9TAkSn6]=mk3SLVN4HKm; delPer=0; PSINO=6; BCLID=8273724148951262294; BCLID_BFESS=8273724148951262294; BDSFRCVID=JBKOJexroG0uo4JjVBHvhB41J_weG7bTDYrEDb8tOfSVLYPVJeC6EG0Pts1-dEu-EHtdogKKy2OTH9DF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; BDSFRCVID_BFESS=JBKOJexroG0uo4JjVBHvhB41J_weG7bTDYrEDb8tOfSVLYPVJeC6EG0Pts1-dEu-EHtdogKKy2OTH9DF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tR3h3RrX26rDHJTg5DTjhPrMy45iWMT-MTryKKJaaKbkjxQtybjsL63LyRnfKx-fKHnRh4oN3n_Wfh7I0pjdWq8ZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPU2H59LUk83gcdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLK-oj-D_9jTrP; H_BDCLCKID_SF_BFESS=tR3h3RrX26rDHJTg5DTjhPrMy45iWMT-MTryKKJaaKbkjxQtybjsL63LyRnfKx-fKHnRh4oN3n_Wfh7I0pjdWq8ZyxomtfQxtNRJQKDE5p5hKq5S5-OobUPU2H59LUk83gcdot5yBbc8eIna5hjkbfJBQttjQn3hfIkj2CKLK-oj-D_9jTrP; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1667022862; APPGUIDE_10_0_2=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; ab_sr=1.0.1_YWQ3OTY4ODIwNGFjNDA3YjM3NGY0NGE4ZGQwY2RkZTU2NDdjNGVkMTVhMzVjNjdmMDA3YThmN2FhZDM1YmI3M2VlOGY1ZWY5NzdkMGQ3ZDU1MzM3YWM0MzVmOGU1NWMyODcwZDE3NGY2ZmM2NTE2MmRhMmMxNGZiNDJkMDM2MDJhY2E1OWZhYWU4NzcwZWExNDliMGJkNzBkMjc0ODUyNA==; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1667025112',
    #'Host': 'fanyi.baidu.com',
    #'Origin':' https://fanyi.baidu.com',
    #'Referer': 'https://fanyi.baidu.com/',
    #'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"',
    #'sec-ch-ua-mobile': '?0',
    #'sec-ch-ua-platform': '"Windows"',
    #'Sec-Fetch-Dest': 'empty',
    #'Sec-Fetch-Mode': 'cors',
    #'Sec-Fetch-Site': 'same-origin',
    #'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
    #'X-Requested-With': 'XMLHttpRequest}',
}
data={
    'from':'en',
    'to':'zh',
    'query':'love',
    'transtype':'realtime',
    'simple_means_flag':'3',
    'sign':'198772.518981',
    'token':'65b3e51de584d7a01742ac55c9f6d303',
    'domain':'common',
}
#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')

import json
obj = json.loads(content)
print(obj)

ajax的get请求豆瓣电影 ,找数据的标头

#(3)数据下载到本地
#open方法默认情况使用的是gbk的编码 无果我们需要保存汉字 那么需要在open方式中指定编码格式utf_8
#encoding='utf-8'
fp=open('douban.json','w',encoding='utf-8')
fp.write(content)

另一种形式(快捷键ctrl+shift+l显示json不是一行)

#with open('douban1.json','w',encoding='utf-8')as fp:
#    fp.write(content)

 

#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':''
}

#(1)请求对象的定制
request=urllib.request.Request(url=url,headers=headers)
#(2)获取响应的数据
response = urllib.request.urlopen(request)
content=response.read().decode('utf-8')
print(content)
#(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页排名,在于接口的寻找

#豆瓣电影前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
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=60&limit=20
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=80&limit=20
#https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=100&limit=20
#page    1  2  3  4  5
#start   0  20 40 60 80
#start (page-1)*20
#下载豆瓣电影前1页的数据
#(1)请求对象的定制
#(2)获取响应的数据
#(3)下载数据

import urllib.parse
import urllib.request
def create_request(page):
    #基础的url
    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': ' '
    }

    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)


网站公告

今日签到

点亮在社区的每一天
去签到

热门文章