欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

利用代理ip池 轻松抓取百万数据。

程序员文章站 2022-05-04 11:49:08
1.今天我们来讲下一个非常有用的东西,代理ip池,结果就是一个任务每隔一定时间去到目标ip代理提供网站去爬取可用数据存到mysql数据库,并且检测数据库已有数据是否可用,不可用就删除。2. 编写 提取代理ip到数据库 的爬虫2.1准备mysql表CREATE TABLE `t_ips` (`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键',`ip` varchar(15) COLLATE utf8_unicode_ci DEFAULT N...

1.今天我们来讲下一个非常有用的东西,代理ip池,结果就是一个任务每隔一定时间去到目标ip代理提供网站去爬取可用数据存到mysql数据库,并且检测数据库已有数据是否可用,不可用就删除。

2. 编写 提取代理ip到数据库 的爬虫

2.1准备mysql表

CREATE TABLE `t_ips` (

`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键',

`ip` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'ip',

`port` int(10) NOT NULL COMMENT 'port',

`type` int(10) NOT NULL DEFAULT '0' COMMENT '0:http 1:https',

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=421 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='ip表';

2.2创建爬虫工程,编写items.py(对应数据库的字段)

import scrapy

class IpsItem(scrapy.Item):

# define the fields for your item here like:

# name = scrapy.Field()

ip = scrapy.Field()

port = scrapy.Field()

httpType = scrapy.Field()

2.3编写settings.py

# -*- coding: utf-8 -*-

####################自已的配置################

MAX_PAGE = 2 ##抓取的代理ip网址 的 页数

#0 : http 1:https

TYPE = 0 ### 代理ip类型

URL = 'http://www.bugng.com/gnpt?page=' ### 代理ip网址

TIMER_STOP_TIME = 20 ### 定时器暂停执行时间

#####################################

BOT_NAME = 'ips'

SPIDER_MODULES = ['ips.spiders']

NEWSPIDER_MODULE = 'ips.spiders'

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'

ITEM_PIPELINES = {

'ips.pipelines.IpsPipeline': 300,

}

# 禁止重试

RETRY_ENABLED = False

# Crawl responsibly by identifying yourself (and your website) on the user-agent

#USER_AGENT = 'csdn (+http://www.yourdomain.com)'

# Obey robots.txt rules

ROBOTSTXT_OBEY = False

# 减小下载超时:

DOWNLOAD_TIMEOUT = 2

# 禁止cookies:

COOKIES_ENABLED = False

# 延迟下载 防止被ban

DOWNLOAD_DELAY=2

2.4编写spider

这里用到了bs4,需要自行安装

# -*- coding: utf-8 -*-

import scrapy

import logging

from bs4 import BeautifulSoup

from ips.items import IpsItem

from ips.settings import *

class XicispiderSpider(scrapy.Spider):

name = 'xiciSpider'

allowed_domains = ['xicidaili.com']

start_urls = ['http://xicidaili.com/']

### 开始 放入url

def start_requests(self):

req = []

for i in range(1,MAX_PAGE):

### 代理ip网址的第几页的 url

req.append(scrapy.Request(URL + str(i-1)))

return req

## 每一页url的 解析回调函数,利用bs4解析

def parse(self, response):

print('@@@@@@@@@ 开始解析 '+response.url)

try:

soup = BeautifulSoup(str(response.body, encoding = "utf-8"),'html.parser')

trs = soup.find('table',{'class':'table'}).find_all('tr')

for tr in trs[1:]:

tds = tr.find_all('td')

cur = 0

item = IpsItem()

item['httpType'] = TYPE

for td in tds:

if cur == 0:

item['ip'] = td.text

if cur == 1:

item['port'] = td.text

cur = cur +1

yield item #### 给pipline处理

except Exception as e:

logging.log(logging.WARN, '@@@@@@@@@ start parser ' + str(e)) 

2.5编写pipline

这里需要安装 : pip install mysqlclient

这里插入数据库之前做两个校验:

1.数据是否存在

2.数据是否可用

# -*- coding: utf-8 -*-

import MySQLdb

import MySQLdb.cursors

from twisted.enterprise import adbapi

import logging

import requests

class IpsPipeline(object):

def __init__(self):

dbargs = dict(

host='你的数据库ip',

db='数据库名称',

user='root',

passwd='数据库密码',

charset='utf8',

cursorclass=MySQLdb.cursors.DictCursor,

use_unicode=True,

)

self.dbpool = adbapi.ConnectionPool('MySQLdb', **dbargs)

##处理每个yeild的item

def process_item(self, item, spider):

res = self.dbpool.runInteraction(self.insert_into_table, item)

return item

def insert_into_table(self, conn, item):

ip = item['ip']

port = item['port']

# 先查询存不存在

if self.exsist(item,conn):

return

# 查询 此代理ip是否可用,可用就加入数据库

if self.proxyIpCheck(item['ip'],item['port']) is False:

print("此代理ip不可用,proxy:",item['ip'],':',str(item['port']))

return

sql = 'insert into t_ips (ip,port,type) VALUES ('

sql = sql + '"' + item['ip'] + '",'

sql = sql + str(item['port']) + ','

sql = sql + str(item['httpType']) + ','

sql = sql[0:-1]

sql = sql + ')'

try:

conn.execute(sql)

print(sql)

except Exception as e:

logging.log(logging.WARNING, "sqlsqlsqlsqlsqlsqlsql error>> " + sql)

def exsist(self,item,conn):

sql = 'select * from t_ips where ip="' + item['ip'] + '" and port=' + str(item['port']) + ''

try:

# 执行SQL语句

conn.execute(sql)

# 获取所有记录列表

results = conn.fetchall()

if len(results) > 0: ## 存在

#print("此ip已经存在@@@@@@@@@@@@")

return True

except:

return False

return False

##判断代理ip是否可用

def proxyIpCheck(self,ip, port):

server = ip + ":" + str(port)

proxies = {'http': 'http://' + server, 'https': 'https://' + server}

try:

r = requests.get('https://www.baidu.com/', proxies=proxies, timeout=1)

if (r.status_code == 200):

return True

else:

return False

except:

return False

2.6 测试爬虫 scrapy crwal 爬虫名

3. 到此我们的 提取代理ip到数据库的 爬虫就写好了,接下来就是我们的任务定时器的编写

#####在我们的爬虫项目的settings.py文件的同级目录新建一个start.py文件

import os

import pymysql

import threading

from settings import *

##定时器调用的run方法

def run():

clearIpPool()

### 循环定时器,不然执行一次就over了

timer = threading.Timer(TIMER_STOP_TIME, run)

timer.start()

########从这里开始执行

print("ip池定时器开始,间隔时间:",str(TIMER_STOP_TIME),'s')

########开启定时器 TIMER_STOP_TIME为settings.py中的配置

timer = threading.Timer(TIMER_STOP_TIME,run)

timer.start()

def clearIpPool():

print("定时器执行,清扫ip数据库池")

## 利用 系统scrapy命令重新爬取代理ip

os.system('scrapy crawl xiciSpider --nolog')

# 遍历数据库 去除无用的代理ip

removeUnSafeProxyFromDB()

print("定时器执行完毕")

###### 查询数据库,找出无用的代理ip并且删除

def removeUnSafeProxyFromDB():

# 打开数据库连接

db = pymysql.connect("39.108.112.254", "root", "abc123|||456", "xici")

# 使用cursor()方法获取操作游标

cursor = db.cursor()

# SQL 查询语句

sql = "SELECT * FROM t_ips"

try:

# 执行SQL语句

cursor.execute(sql)

# 获取所有记录列表

results = cursor.fetchall()

for row in results:

id = row[0]

ip = row[1]

port = row[2]

if proxyIpCheck(ip, str(port)) is False:

print("此代理ip不可用,proxy:",ip, ':', str(port))

## 执行删除

sql = "DELETE FROM t_ips WHERE id = "+str(id)

# 执行SQL语句

cursor.execute(sql)

print(sql)

# 提交修改

db.commit()

return

except:

print("Error: unable to fetch data")

# 关闭数据库连接

db.close()

#####检测代理ip是否可用

def proxyIpCheck(ip, port):

server = ip + ":" + str(port)

proxies = {'http': 'http://' + server, 'https': 'https://' + server}

try:

r = requests.get('https://www.baidu.com/', proxies=proxies, timeout=1)

if (r.status_code == 200):

return True

else:

return False

except:

return False 

本文地址:https://blog.csdn.net/yingpu618/article/details/108264545

相关标签: 代理ip 爬虫