Python笔记:第三方IP代理服务与爬虫IP代理

代理服务

  • 我们在做爬虫的过程中经常最初爬虫都正常运行,正常爬取数据,一切看起来都是美好,然而一会儿功夫就出现了错误。

  • 如:403 Forbidden错误,“您的IP访问频率太高”错误,或者跳出一个验证码让我们输入,之后解封,但过一会又出现类似情况。

  • 出现这个现象的原因是因为网站采取了一些反爬中措施,如:服务器检测IP在单位时间内请求次数超过某个阀值导致,称为封IP。

  • 为了解决此类问题,代理就派上了用场,如:代理软件、付费代理、ADSL拨号代理,以帮助爬虫脱离封IP的苦海。

  • 测试HTTP请求及响应的网站:http://httpbin.org/

    • httpbin这个网站能测试 HTTP 请求和响应的各种信息,比如 cookie、ip、headers 和登录验证等.
    • 且支持 GET、POST 等多种方法,对 web 开发和测试很有帮助。
      • GET地址 :http://httpbin.org/get
      • POST地址:http://httpbin.org/post
    • 它用 Python + Flask 编写,是一个开源项目。开源地址:https://github.com/Runscope/httpbin
    • 返回信息中origin的字段就是客户端的IP地址,即可判断是否成功伪装IP

代理设置

1 ) urllib的代理设置

from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener

proxy = '127.0.0.1:8888'
#需要认证的代理
#proxy = 'username:[email protected]:8888'

#使用ProxyHandler设置代理
proxy_handler = ProxyHandler({
    'http': 'http://' + proxy,
    'https': 'https://' + proxy
})
#传入参数创建Opener对象
opener = build_opener(proxy_handler)
try:
    response = opener.open('http://httpbin.org/get')
    print(response.read().decode('utf-8'))
except URLError as e:
    print(e.reason)

2 ) requests的代理设置

import requests

proxy = '127.0.0.1:8888'
#需要认证的代理
#proxy = 'username:[email protected]:8888'

proxies = {
    'http': 'http://' + proxy,
    'https': 'https://' + proxy,
}
try:
    response = requests.get('http://httpbin.org/get', proxies=proxies)
    print(response.text)
except requests.exceptions.ConnectionError as e:
    print('Error', e.args)

3 ) Selenium的代理使用

使用的是PhantomJS

from selenium import webdriver

service_args = [
    '--proxy=127.0.0.1:9743',
    '--proxy-type=http',
    #'--proxy-auth=username:password' #带认证代理
]

browser = webdriver.PhantomJS(service_args=service_args)
browser.get('http://httpbin.org/get')
print(browser.page_source)

使用的是Chrome

from selenium import webdriver

proxy = '127.0.0.1:9743'
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--proxy-server=http://' + proxy)
chrome = webdriver.Chrome(chrome_options=chrome_options)
chrome.get('http://httpbin.org/get')

4 ) 在Scrapy使用代理

扫描二维码关注公众号,回复: 8956970 查看本文章
#在Scrapy的Downloader Middleware中间件里
# ...
def process_request(self, request, spider):
    request.meta['proxy'] = 'http://127.0.0.1:9743'
# ...

免费代理IP的使用

我们可以从互联网中获取免费的代理IP:如:西刺 http://www.xicidaili.com

import requests,random

#定义代理池
proxy_list = [
    '182.39.6.245:38634',
    '115.210.181.31:34301',
    '123.161.152.38:23201',
    '222.85.5.187:26675',
    '123.161.152.31:23127',
]

# 随机选择一个代理
proxy =  random.choice(proxy_list)

proxies = {
    'http': 'http://' + proxy,
    'https': 'https://' + proxy,
}
try:
    response = requests.get('http://httpbin.org/get', proxies=proxies)
    print(response.text)
except requests.exceptions.ConnectionError as e:
    print('Error', e.args)

收费代理IP的使用

1 ) 收费代理服务商

  • 西刺:http://www.xicidaili.com
  • 讯代理:http://www.xdaili.cn/
  • 快代理:https://www.kuaidaili.com/
  • 大象代理:http://www.daxiangdaili.com/

2 )在requests中使用收费代理

import requests

# 从代理服务中获取一个代理IP
proxy =  requests.get("http://tvp.daxiangdaili.com/ip/?tid=此处填写订单号&num=1").text
proxies = {
    'http': 'http://' + proxy,
    'https': 'https://' + proxy,
}
try:
    response = requests.get('http://httpbin.org/get', proxies=proxies)
    print(response.text)
except requests.exceptions.ConnectionError as e:
    print('Error', e.args)

3 ) 在scrapy中使用收费代理

  • 创建scrapy项目:$ scrapy startproject httpbin

  • 创建爬虫项目

    cd httpbin
    scrapy genspider hb httpbin.org
    
  • 编写代码

    • 编写爬虫文件hb.py
    import scrapy
    
    class HbSpider(scrapy.Spider):
        name = 'hb'
        allowed_domains = ['httpbin.org']
        start_urls = ['http://httpbin.org/get']
    
        def parse(self, response):
            print(response.body)
    
    • 编写中间件文件:middlewares.py
    class HttpbinProxyMiddleware(object):
        def process_request(self, request, spider):
            pro_addr = requests.get('http://127.0.0.1:5000/get').text
            request.meta['proxy'] = 'http://' + pro_addr
    
    • 修改配置文件settings.py
    ROBOTSTXT_OBEY = False #关闭爬虫协议
    
    DOWNLOADER_MIDDLEWARES = {
        'httpbin.middlewares.HttpbinProxyMiddleware': 543,
    }
    
    #关闭终端输出,改输出到指定日志文件中
    LOG_LEVEL= 'DEBUG'
    
    LOG_FILE ='log.txt'
    
  • 执行信息爬取测试: $ scrapy crawl hb

使用代理抓取信息案例

1 )任务

  • 利用代理爬取微信公众号的文章信息,从中提取标题、摘要、发布日期、公众号以及url地址等内容。

  • 爬取的是搜索关键字为python的,类别为微信的所有文章信息,并将信息存储到MongoDB中。

  • URL地址:http://weixin.sogou.com/weixin?type=2&query=python&ie=utf8&s_from=input

2 ) 分析

  • 首先对要爬取的微信公众号的文章信息进行分析,确定url地址
  • 分析要爬取的信息加载方式,确定属性普通加载(在响应里使用xpath或css解析)
  • 分析如何获取更多页信息的爬取。就是如何跳转下一页。(没有登录的用户只能看到10页,登陆后才可看到其他页)
  • 本次案例需要使用的Python库:Scrapy、requests、pymongo
  • 在MongoDB中创建一个数据库wenxin,让后在此库中创建一个集合wx,最后开启MongoDB数据库

3 ) 具体实现

3.1 创建项目

  • 首先新建项目,名为weixin:$scrapy startproject weixin

  • 进入项目weixin目录下,创建一个Spider(爬虫类wx):

    cd weixin
    scrapy genspider wx weixin.sogou.com
    
  • 进入settings.py的配置文件:将ROBOTSTXT_OBEY改为false,忽略爬虫协议 $ROBOTSTXT_OBEY = False

3.2 定义Item类

# 定义信息封装类(标题、摘要、公众号、时间、URL地址)
import scrapy

class WxItem(scrapy.Item):
    # define the fields for your item here like:
    collection = 'wx'
    title = scrapy.Field()
    content = scrapy.Field()
    nickname = scrapy.Field()
    date = scrapy.Field()
    url = scrapy.Field()

3.3 解析页面

  • 进入spider/wx.py文件中编写:
# -*- coding: utf-8 -*-
import scrapy
from weixin.items import WxItem

class WxSpider(scrapy.Spider):
    name = 'wx'
    allowed_domains = ['weixin.sogou.com']
    start_urls = ['http://weixin.sogou.com/weixin?query=python&type=2&page=1&ie=utf8']

    def parse(self, response):
        if response.status != 200:
            yield scrapy.Request(url=response.url,callback=sself.parse)
        # 解析出当前页面中的所有文章
        ullist = response.selector.css("ul.news-list li")
        # 遍历文章
        for ul in ullist:
            #解析具体信息并封装到item中
            item = WxItem()
            item['title'] = ul.css("h3 a").re_first("<a.*?>(.*?)</a>")  
            item['content'] = ul.css("p.txt-info::text").extract_first()
            item['nickname'] = ul.css("a.account::text").extract_first()
            item['date'] = ul.re_first("document.write\(timeConvert\('([0-9]+)'\)\)")
            item['url'] = ul.css("h3 a::attr(href)").extract_first()
            # print(item)
            # 交给pipelines(item管道)处理
            yield item

        #解析出下一頁的url地址
        next_url = response.selector.css("#sogou_next::attr(href)").extract_first()
        #判断是否存在
        if next_url:
            url = response.urljoin(next_url) #构建绝对url地址
            yield scrapy.Request(url=url,callback=self.parse) #交给调度去继续爬取下一页信息

3.4 存储结果

首先开启相关配置, 修改配置文件settings.py信息:(开启MongoPipeline管道类,设置MongoDB的连接信息)

ITEM_PIPELINES = {
    'scrapyseleniumtest.pipelines.MongoPipeline': 300,
}

MONGO_URI = 'localhost'

MONGO_DB = 'weixin'

针对pipeline文件进行编写

import pymongo

class MongoPipeline(object):
    ''' 完成MongoDB数据库对Item信息的存储'''

    def __init__(self, mongo_uri, mongo_db):
        '''对象初始化'''
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        '''通过依赖注入方式实例化当前类,并返回,参数是从配置文件获取MongoDB信息'''
        return cls(mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DB'))

    def open_spider(self, spider):
        '''Spider开启自动调用此方法,负责连接MongoDB,并选择数据库'''
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def process_item(self, item, spider):
        '''选择对应集合并写入Item信息'''
        self.db[item.collection].insert(dict(item))
        return item

    def close_spider(self, spider):
        '''Spider关闭时自动调用,负责关闭MongoDB的连接'''
        self.client.close()

3.5 执行爬虫文件开始信息爬取

  • $scrapy crawl wx

  • 注意:当前爬取信息过多时会报如下302错误:(IP访问频繁需要进行验证)

    [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (
    302) to <GET http://weixin.sogou.com/antispider/?from=%2fweixin%3Fquery%3dpython
    %26type%3d2%26page%3d1%26ie%3dutf8> from <GET http://weixin.sogou.com/weixin?que
    ry=python&type=2&page=1&ie=utf8>
    

3.6 在中间件中使用付费代理服务来解决上面错误

# 在middlewares.py文件中定义一个Downloader中间件
import requests
class HttpbinProxyMiddleware(object):
    def process_request(self, request, spider):
        # 此处用的是大象代理
        pro_addr = requests.get('http://tvp.daxiangdaili.com/ip/?tid=这里填写你的订单号,详见大象代理API文档&num=1').text
        request.meta['proxy'] = 'http://' + pro_addr
        # 设置启动上面我们写的这个代理

#在settings.py配置文件中.设置我们自定义的Downloader MiddleWares中间件设置:
DOWNLOADER_MIDDLEWARES = {
   'httpbin.middlewares.HttpbinProxyMiddleware': 543,
}
发布了390 篇原创文章 · 获赞 183 · 访问量 67万+

猜你喜欢

转载自blog.csdn.net/Tyro_java/article/details/104046138