210303课 解决爬虫时IP封禁问题
爬取豆瓣电影Top250的详情信息并写入Excel文件
1,抓取页面 >拿HTML源代码 requests
response.text
response.content.decode(’…’)
2,解析页面 >正则 用re模块
CSS选择器 用BeautifulSoup
XPath 用lxml
3,保存数据 >持久化处理 >数据分析(从数据中找出有用的信息)
CSV >csv系统自带原生版本
Excel >xlwt旧版 / openpyxl新版用法/
# 导入相关模块
import bs4
import requests
import openpyxl
import time
import random
# 将表头前置,避免后面重复写
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/88.0.4324.192 Safari/537.36'
}
# proxies = {
# 'https': '此处为代理商的url'
# }
# 封装一个用来获取电影详情的函数
def fetch_movie_detail(url):
# 根据指定的URL抓取电影的详情信息(类型和时长)
resp = requests.get(url=url, headers=headers)
# 下定义:如果能正常运行
if resp.status_code == 200:
# 解析页面
soup = bs4.BeautifulSoup(resp.text, 'html.parser')
# 用CSS选择器拿到span标签里面的属性标签genre
# 电影类型有多个,片长一般为一个
genre_spans = soup.select('span[property="v:genre"]')
# 拿片长标签
runtime_span = soup.select_one('span[property="v:runtime"]')
# 用join函数通过列表推导式把电影类型和片长用指定元素拼接起来
gener = '/'.join([genre_span.text for genre_span in genre_spans])
runtime = runtime_span.attrs['content']
return [gener, runtime]
def main():
# 创建工作簿对象
wb = openpyxl.Workbook()
# 添加一张工作表
sheet = wb.create_sheet('Top250')
# 设定行数从0开始
row_num = 0
# 定义列名
column_names = ('编号', '片名', '评分', '名句', '类型', '时长')
# 对列里面的内容进行遍历
for col, column_name in enumerate(column_names):
sheet.cell(row_no + 1, col + 1, column_name)
try:
for page in range(10):
# 抓取页面
resp = requests.get(
url=f'https://movie.douban.com/top250?start={page * 25}',
headers=headers
)
if resp.status_code == 200:
# 解析页面
soup = bs4.BeautifulSoup(resp.text, 'html.parser')
# 拿电影的a标签,方便后续拿子页面的信息:例如时长
anchors = soup.select('div.info > div.hd > a')
# 拿标题对应的标签
title_spans = soup.select('div.info > div.hd > a > span:nth-child(1)')
# 拿评分对应的标签
rating_spans = soup.select('span.rating_num')
# 拿电影名言对应的标签
quote_spans = soup.select('p.quote > span')
# 将上面的4个标签压缩到一起,形成一个序列
for anchor, title_span, rating_span, quote_span in zip(anchors, title_spans, rating_spans, quote_spans):
row_no += 1
# 拿电影详情页子页面的url
detail_url = anchor.attrs['href']
# 将3项初级页面的信息放到一个列表里
movie_infos = [row_no, title_span.text, rating_span.text, quote_span.text]
movie_infos += fetch_movie_detail(detail_url)
print(movie_infos)
for col, info in enumerate(movie_infos)
sheet.cell(row_no + 1, col + 1, info)
else:
print(f'请求失败,响应状态码:{resp.status_code}')
except Exception as err:
print(err)
finally:
wb.save('豆瓣电影.xlsx')
if __name__ == '__main__':
main()
处理封ip问题
方法一:
服务器提示登陆后再用,服务器会识别身份,后期容易有麻烦
登陆和未登录的cookie不同
未登录的一般没有cookie
方法二:
使用商业代理:高匿代理
隐匿自己身份
突破网站对访问ip段的限制
通过多个ip代理轮流使用,避免一个ip地址被限流或封禁
优秀的商业ip代理品牌:可用性,访问速度,价格
蘑菇代理,芝麻代理,快代理,讯代理,阿布云代理
1)服务器识别用户登录的原理
第一种:
用户登录成功后,服务器Network里面会创建一个Session会话对象,此对象保存了用户相关数据
并让浏览器记录一条Cookie数据来保存Session的id
服务器会根据此id匹配Session
第二种:
服务器中不保存任何对象,服务器会将用户数据生成一个身份令牌
返回给浏览器(服务器Application里面的Storage里面可以保存数据)
2) JSON > javascript object notation
原先是一种输入语法,现在普遍用于2个机器间传输数据
JSON格式的数据是纯文本,任何系统都能读纯文本
可以在异构(不同配置)系统间交换数据
JSON输出的纯文本是字典格式(键值对用双引号圈起来),与Python契合度高
目前使用的交换数据的格式有3种:都是纯文本,JSON最好用
XML
JSON
YAML
Python里面的json模块可以实现json与字典的双向转换
> dumps 字典变字符串
>> dump 把文件里的字典变字符串
> loads 字符串变字典
>> load 把文件里的字符串变字典
import json
person_info = {
"name": "June",
"age": "18",
"sex": "women"
}
# 创建一个json文件,以字典形式打开
# with open('person.json', 'w') as file:
#json.dump(person_info, file)
with open('person.json', 'r') as file:
json.load(person_info, file)
print(type(person_info))
print(person_info)
3)从商业ip代理获取代理服务器地址并保存到文件的方法
在商业爬虫项目中需要建立代理池,此法比较复杂,要对每个ip计数以便随时更新替换
> 加载代理服务器数据并保存
> 监控所有的代理服务器,及时移除失效的服务器
提供一个接口能够随机选中某个代理服务器
import json
import time
import requests
# 把所有的代理放到一个空列表里
all_proxies = []
# 对取到的数据进行循环
for _ in range(10):
# 申请url
resp = requests.get(
'http://piping.mogumiao.com/proxy/api/get_ip_bs?'
'appKey=20c3b5de1fa14df7baeb608aa09971de&count=5&expiryDate=0&format=1&newLine=2'
)
data = resp.json()
if data['code'] == '0':
print(data['msg'])
all_proxies += data['msg']
time.sleep(11)
with open('proxy.json', 'w') as file:
json.dump(all_proxies, file)