210303课 解决爬虫时IP封禁问题

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)

猜你喜欢

转载自blog.csdn.net/AncenaJune/article/details/114335109