Python_01_IP代理池_实现代理池的爬虫模块的通用爬虫

    需求:抓取各个代理ip网站上的免费代理ip,进行检测,如果可用储存到数据库汇总

    代理ip网站:

  http://www.ip3366.net/free/?stype=1&page=1

  https://www.kuaidaili.com/free/inha/1

  http://www.66ip.cn/1.html  

  https://www.xicidaili.com/nn/1

点开网页发现各个网站的url是有规律的.

    思路:

      通用爬虫:通过制定url列表,分组xpath和组内xpath,来提取不同网站的代理ip

        原因:代理ip的页面结构几乎都是table.

      具体爬虫:用于抓取具体代理ip网站

        通过集成通用爬虫来实现具体网站的抓取,一般只需要制定爬取的url列表,分组的xpath和组内xpath即可

      爬虫运行模块:启动爬虫,抓取代理ip,进行检测,如果可用保存到数据库中

        通过配置文件来控制启动哪些爬虫,增加扩展性,如果我们遇到返回json格式的代理网站,单独写一个即可

     

    实现通用爬虫:

      目标:实现一个可以通过制定不同url列表,分组的xpath和详情的xpath,从不同页面上提取数据的通用爬虫.

      步骤:

        在base_spider.py中定义一个BaseSpider类,继承object

        提供三个成员变量:

          urls:代理ip网址的url列表

          group_xpath:分组xpath,获取包含代理ip详细的信息的列表的xpath

          detail_xpath:组内xpath,过去代理ip详细信息xpath,格式为{'ip':"xxx",'port':'xxx','area':'xxx'}

      提供原始方法,传入爬虫url列表,分组xpath,组内xpath

      对外提供一个获取代理ip的方法

        遍历url列表获取url

        根据发送请求,获取页面数据

        解析页面,提取数据,转为proxy对象

        返回proxy对象列表

代码:

import requests
from utils.http import get_request_headers
from lxml import etree
from domain import Proxy

"""
8.3 实现通用爬虫
目标: 实现可以指定不同URL列表, 分组的XPATH和详情的XPATH, 从不同页面上提取代理的IP,端口号和区域的通用爬虫;
步骤:

1. 在base_spider.py文件中,定义一个BaseSpider类, 继承object
2. 提供三个类成员变量:
    urls: 代理IP网址的URL的列表
    group_xpath: 分组XPATH, 获取包含代理IP信息标签列表的XPATH
    detail_xpath: 组内XPATH, 获取代理IP详情的信息XPATH, 格式为: {'ip':'xx', 'port':'xx', 'area':'xx'}
3. 提供初始方法, 传入爬虫URL列表, 分组XPATH, 详情(组内)XPATH
4. 对外提供一个获取代理IP的方法
    4.1 遍历URL列表, 获取URL
    4.2 根据发送请求, 获取页面数据
    4.3 解析页面, 提取数据, 封装为Proxy对象
    4.4 返回Proxy对象列表
"""

# 1. 在base_spider.py文件中,定义一个BaseSpider类, 继承object
class BaseSpider(object):

    # 2. 提供三个类成员变量:
    # urls: 代理IP网址的URL的列表
    urls = []
    # group_xpath: 分组XPATH, 获取包含代理IP信息标签列表的XPATH
    group_xpath = ''
    # detail_xpath: 组内XPATH, 获取代理IP详情的信息XPATH, 格式为: {'ip':'xx', 'port':'xx', 'area':'xx'}
    detail_xpath = {}

    # 3. 提供初始方法, 传入爬虫URL列表, 分组XPATH, 详情(组内)XPATH
    def __init__(self, urls=[], group_xpath='', detail_xpath={}):

        if urls:
            self.urls = urls

        if group_xpath:
            self.group_xpath = group_xpath

        if detail_xpath:
            self.detail_xpath = detail_xpath

    def get_page_from_url(self, url):
        """根据URL 发送请求, 获取页面数据"""
        response = requests.get(url, headers=get_request_headers())
        print(url)
        print(response.status_code)
        return response.content


    def get_first_from_list(self, lis):
        # 如果列表中有元素就返回第一个, 否则就返回空串
        return lis[0] if len(lis) != 0 else ''


    def get_proxies_from_page(self, page):
        """解析页面, 提取数据, 封装为Proxy对象"""
        element = etree.HTML(page)
        # 获取包含代理IP信息的标签列表
        trs = element.xpath(self.group_xpath)
        # 遍历trs, 获取代理IP相关信息
        for tr in trs:
            ip = self.get_first_from_list(tr.xpath(self.detail_xpath['ip']))
            port = self.get_first_from_list(tr.xpath(self.detail_xpath['port']))
            area = self.get_first_from_list(tr.xpath(self.detail_xpath['area']))
            proxy = Proxy(ip, port, area=area)
            # print(proxy)
            # 使用yield返回提取到的数据
            yield proxy


    def get_proxies(self):
        # 4. 对外提供一个获取代理IP的方法
        # 4.1 遍历URL列表, 获取URL
        for url in self.urls:
            # print(url)
            # 4.2 根据发送请求, 获取页面数据
            page = self.get_page_from_url(url)
            # 4.3 解析页面, 提取数据, 封装为Proxy对象
            proxies = self.get_proxies_from_page(page)
            # 4.4 返回Proxy对象列表
            yield from proxies


if __name__ == '__main__':

    config = {
        'urls': ['http://www.ip3366.net/free/?stype=1&page={}'.format(i) for i in range(1, 4)],
        'group_xpath': '//*[@id="list"]/table/tbody/tr',
        'detail_xpath': {
            'ip':'./td[1]/text()',
            'port':'./td[2]/text()',
            'area':'./td[5]/text()'
        }
    }

    spider = BaseSpider(**config)
    for proxy in spider.get_proxies():
        print(proxy)

          

 

  

  

 

猜你喜欢

转载自www.cnblogs.com/tkg1314/p/12611601.html