one
1.爬虫的简介
1.什么是爬虫:
1.什么是互联网:
互联网是有网络设备(网线,路由器等)和一台台计算机链接而成的,像一张网。
2.什么是上网:
我们所谓的上网便是有用户计算机发送的请求给目标计算机,将目标计算机的数据下载到本地的过程。
- 只不过,用户获取网络数据的方式是:浏览器的提交请求----》下载页面代码-----》只提取有用的数据-----》存放于数据库的文件中
- 爬虫要做的:模拟浏览器发送请求:---下载页面代码-----只提取有用的数据-----存放于数据库中或者文件当中
3.总结:
就是把互联网比作一个大网,而爬虫就是网上的蜘蛛,在这张网上吧数据获取下来,
定义:向网站发起请求,获取资源后分析并提取有用的数据
相当于掌握了爬虫的技能,就可以在网上获取有价值的数据
2.爬虫的流程:
---->发送请求(使用http库想目标地点发送请求,发送一个request,request包括请求头以及请求体等)
---->获取页面的内容(如果服务能正常相应,则会得到一个response,response包含这我们想要的数据)
---->解析内容(解析html数据,利用正则表达式或者第三方解析库beautifulsoup等,解析json的数据:json模块,解析二进制数据,以b的方式写入文件)
---->保存数据(将数据保存到数据库中或者文件当中)
3简单的爬虫示例(爬取校花网的视屏)
- 版本一(没有使用多进程就是简单的单个视屏的下载一个获取页面)
#下面的这个版本是最基础的,但是运行的时候你会发现下载的是一个一个下载的,有点慢。
import requests #pip3 install requests
import re
import hashlib
import time
movie_path=r'E:\little_film'#先制定要存放的路径
def get_page(url):
"""
如果状态码返回的是200,则证明访问成功,但是,也不一定,因为有时候不写referer,也会返回200,但是页面是无法访问的,所以要赢try,except
:param url:
:return:
"""
try:
response=requests.get(url)#以get的请求访问url
if response.status_code == 200:#状态码
return response.text#返回html页面,还有一个connect,这个就是返回的字节类型的页面
except Exception:
pass
def parse_index(index_page):
urls=re.findall('class="items".*?href="(.*?)"',index_page,re.S)#正则表达式处理re.S,因为会匹配到很多的url所以用urls列表接受
for url in urls:
if not url.startswith('http'):#这里是处理url因为有的url不完整
url='http://www.xiaohuar.com'+url
yield url#用yield生成器用一个返回一个
def parse_detail(detail_page):
l=re.findall('id="media".*?src="(.*?)"',detail_page,re.S)
if l:
movie_url=l[0]
if movie_url.endswith('mp4'):#这里是处理url因为有的url不是从指定的路径过来的,如果不是从指定的路径过来的话,获取url需要重新更改
yield movie_url
def get_movie(url):
try:#用try的原因跟上面的一样
response=requests.get(url)
if response.status_code == 200:
#以下的代码就是为了方便文件名的不重复,利用hushlib和time
m=hashlib.md5()
m.update(str(time.time()).encode('utf-8'))
m.update(url.encode('utf-8'))
filepath='%s\%s.mp4' %(movie_path,m.hexdigest())
with open(filepath,'wb') as f:
f.write(response.content)
print('%s 下载成功' %url)
except Exception:
pass
def main():
base_url='http://www.xiaohuar.com/list-3-{page_num}.html'
for i in range(5):
url=base_url.format(page_num=i)
index_page=get_page(url)
detail_urls=parse_index(index_page)
for detail_url in detail_urls:
detail_page=get_page(detail_url)
movie_urls=parse_detail(detail_page)
for movie_url in movie_urls:
get_movie(movie_url)
if __name__ == '__main__':
main()
- 版本二(利用多线程,来同时下载多个视频)
import requests #pip3 install requests
import re
import hashlib
import time
from concurrent.futures import ThreadPoolExecutor
pool=ThreadPoolExecutor(50)
movie_path=r'E:\little_film'
def get_page(url):
try:
response=requests.get(url)
if response.status_code == 200:
return response.text
except Exception:
pass
def parse_index(index_page):
index_page=index_page.result()
urls=re.findall('class="items".*?href="(.*?)"',index_page,re.S)
for detail_url in urls:
if not detail_url.startswith('http'):
detail_url='http://www.xiaohuar.com'+detail_url
pool.submit(get_page,detail_url).add_done_callback(parse_detail)
def parse_detail(detail_page):
detail_page=detail_page.result()
l=re.findall('id="media".*?src="(.*?)"',detail_page,re.S)
if l:
movie_url=l[0]
if movie_url.endswith('mp4'):
pool.submit(get_movie,movie_url)
def get_movie(url):
try:
response=requests.get(url)
if response.status_code == 200:
m=hashlib.md5()
m.update(str(time.time()).encode('utf-8'))
m.update(url.encode('utf-8'))
filepath='%s\%s.mp4' %(movie_path,m.hexdigest())
with open(filepath,'wb') as f:
f.write(response.content)
print('%s 下载成功' %url)
except Exception:
pass
def main():
base_url='http://www.xiaohuar.com/list-3-{page_num}.html'
for i in range(5):
url=base_url.format(page_num=i)
pool.submit(get_page,url).add_done_callback(parse_index)
if __name__ == '__main__':
main()
2.request请求:
1.请求方式:
常用的请求方式有:GET,POST
其他的请求方式:delete,head,put,opthons等
get的请求最终会凭拼接成:k1=xxx&k2=yyy&k3=zzz
post会放在请求体中
2.请求的url
url全程为统一资源定位符
3.请求头
User-agent:请求头中如果没有user-agent客户端配置,服务端可能将你当做一个非法用户
host
cookies:cookie用来保存登录信息
一般做爬虫都会加上请求头(常用的)
4.请求体
如果是get请求,请求体没有内容
如果是post请求,请求体是format data
3.response相
1.响应的状态:
200:代表成功(就算是200也比一定成功)
301:代表跳转
404:文件不存在
403:权限
502:服务器的问题
2.响应头
set-cookie:可能有多个,是来告诉浏览器,吧cookie保存下来
3.preview就是网页源代码
最主要的部分就是包含了请求资源的内容
4.requests的可以模拟浏览器的get请求,比起之前的urllib,requests模块的api更加的便捷(本质就是封装了urllib3)
(注意:requests的库发送的请求将页面下载下来之后,并不会执行js代码,这需要我们自己分析目标站点然后发送新的request的请求)
使用之前一定要安装requests
- 常用的请求方式:
示例代码:
import requests
r = requests.get("url")
r = requests.post("url",data = {'key':'value'})
1.基于get请求:
1.基本的请求:
response = requests.get("https://www.baidu.com/")
print(response.text)#获取页面的html的文本文件
print(response.content)#获取页面html页面代码(只不过是以字节的方式获取)
如果要爬去一些比较正规的网站,必须要加上请求头,如果不加的话,有的网站是无法访问的!
示例代码:
response = requests.get("https://www.baidu.com/",
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36Query String Parametersview sourceview URL encoded"
})#在请求头中将自己伪装成浏览器,否则浏览器会认为你是Python程序,或者网站不会让你访问的!
2.带参数的get请求:
#这里是第一种方式
在百度中查询是的url:https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3
如果在查询的时候,关键字是中文的或者是特殊的字符,就必须要进行编码
示例代码:
import requests
from urllib.parse import urlencode#导入的这个模块是用来转换编码格式的!
wd = "美女"
encode_res = urlencode({"wd":wd},encoding="utf-8")#这里是一个把字典转换成 wd=%E7%BE%8E%E5%A5%B3
keyword = encode_res.split('=')[1]#切分得到自己想要的拼接的值
#然后拼接url
url='https://www.baidu.com/s?wd=%s&pn=1' %keyword
response = requests.get(url,
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36Query String Parametersview sourceview URL encoded"
})
print(response.text)#获取页面的html的文本文件
#第二种方式就是利用requests的params的参数搞定本质还是上面的urlencode
wd = "美女"
pn = 10
url='https://www.baidu.com/s'
response = requests.get(url,
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36Query String Parametersview sourceview URL encoded"
},params={
"wd":wd,
"pn":pn
})
3.带参数的get请求的headers
#通常我们在发送请求时都需要带上请求头,请求头是将自己的Python程序伪装成浏览器来访问网站的
常用的请求头参数有:
HOST,
refere:#大型网站都会根据这个参数来判断请求的来源
user_agent:#这个就是将自己的程序伪装成一个浏览器
cookie:#因为cookie相对来说比较重要,所以requests的模块会有相应的参数来处里,所以就没必要往header里面放l
添加headers(浏览器会识别请求头,不加可能会被拒绝访问)
示例代码;
#自己定制headers
wd = "美女"
pn = 10
url = 'https://www.baidu.com/s'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36Query String Parametersview sourceview URL encoded",
}
response = requests.get(url, headers=headers, params={"wd": wd, "pn": pn},
)
print(response.text)
4.带参数的get请求的cookie:
#从浏览器中获取cookies,以后就可以直接拿着cookie登录了,无需输入用户名密码
wd = "美女"
pn = 10
url = 'https://www.baidu.com/s'
Cookie={'PSTM':'1510705099'}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36Query String Parametersview sourceview URL encoded",
}
response = requests.get(url, headers=headers,Cookie={'PSTM':'1510705099'}, params={"wd": wd, "pn": pn},
)
print(response.text)
5.requests可以模拟浏览post请求:
1.介绍;
get请求:
HTTP默认的请求方法就是GET
- 没有请求体
- 数据必须在1K之内!
- GET请求数据会暴露在浏览器的地址栏中
GET请求常用的操作:
- 在浏览器的地址栏中直接给出URL,那么就一定是GET请求
- 点击页面上的超链接也一定是GET请求,提交表单时,表单默认使用GET请求,但可以设置为POST
POST请求
- 数据不会出现在地址栏中
- 数据的大小没有上限
- 有请求体
- 请求体中如果存在中文,会使用URL编码!
#!!!requests.post()用法与requests.get()完全一致,特殊的是requests.post()有一个data参数,用来存放请求体数据
2.发送post请求模拟浏览器的登录行为。
url = 'https://github.com/login'
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"
}
r1 = requests.get(url,headers = headers)
r1_cookie = r1.cookies.get_dict()#以字典的方式拿值闹到的是cookie,没有赋值的cookie
authenticity_token = re.findall(r'name="authenticity_token".*?value="(.*?)"',r1.text)[0]#就是csrftoken
data = {
"commit":"Sign in",
"utf8":"✓",
"authenticity_token":authenticity_token,
"login":"***********",
"password":"*********"
}
r2 = requests.post('https://github.com/session',
data=data,
cookies=r1_cookie
)
login_cookie=r2.cookies.get_dict()
r3=requests.get('https://github.com/settings/emails',
cookies=login_cookie)
print(r3.status_code)
print('***********' in r3.text)
*************************面试题练习*********************
1.如何实现对python列表的去重并保持原先的顺序
- 示例代码
list1 = ['aa', 'bb', 'cc', 'dd', 'aa', 'bb', 'cc']
list2 = list(set(list1))
print(list2)
2.现在有两组元组(('a'),('b')),(('c'),('d')),请使用Python中匿名函数生成列表[{'a':'c'},{'b':'d'}]
- 示例代码
print([{i:j} for i,j in zip((('a'),('b')),(('c'),('d')))])
3.请给出二分法查找的Python代码示例
- 示例代码
lst = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
def dich(lst, tar, start = 0, end = len(lst)-1):
if end < start:
return -1
middle = (start + end) // 2
if lst[middle] < tar:
return dich(lst, tar, middle+1, end)
elif lst[middle] > tar:
return dich(lst, tar, start, middle-1)
else:
return middle
print(dich(lst, 15))
4.在Python的字符串格式化中,%和format的区别;
- %可以匹配很多种,就好比正则一样,例如%s,%S,%d...
- format替换字符串中的占位符
5.*args和**kwargs什么时候回用到,示例代码
- 当一个函数的传参的时候,不确定有多少参数的时候会用到,例如装饰器
- 测试代码
def target(func):
def inner(*args,**kwargs):
print("装饰器")
return func(*args,**kwargs)
return inner
@target
def test():
print("测试代码")
test()
6. 选择题:
- x = 'foo'
y = 2
print(x*y)
答案是:foofoo
x = 'foo'
y = 2
print(x-y)
这样的就是错误的:unsupported operand type(s) for -: 'str' and 'int',提示字符串的int数字类型不能进行加减
7.Python里面是如何实现list和tuple的转换:
- 示例代码:
temp_list2 = [1,2,3,4,5]
print(tuple(temp_list2))
temp_list1 = (1,2,3,4,5)
print(list(temp_list1))
8. 请写出一段Python代码实现删除一个list里面的元素
- list(set(test_list))
9. 什么是lambda表达式:
匿名函数,通常情况下不想写简单的函数就可以用lambda表达式,方便
10.Python2和Python3的区别:
- python2的print不用加()
- Python3的print必须加()否则会报错
- Python2中的raw_input和python3中的input
- python2和python3的编码不同:Python 2 有 ASCII str() 类型,unicode() 是单独的,不是 byte 类型。
......

浙公网安备 33010602011771号