http://blog.csdn.net/mingz_free/article/details/45967725
想要在Scrapy领域无限制畅游,做好伪装是第一步,于是乎,抓取代理IP成了很多教程的开始部分。
我十分同意这个观点,既有实际用处,又能作为一个教学,当然,对于初次使用scrapy的我,很多东西也只是在摸索阶段,所以以下内容算不上教学,只能说是练手。
完成代理IP抓取,总共分三个步骤:
- 抓取网络上的代理IP和端口
- 验证已经抓取的内容
- 网络上的免费代理IP基本都有时效性,所以需要重复抓取和重复验证
这里需要用到的解决方案是:scrapy+mongo+supervisor,scrapy负责抓取,mongo是数据存储的解决方案,supervisor负责监控一个daemon,重复验证已经获得的代理IP。
scrapy教程推荐看官方的版本:scrapy官方文档,即使是翻译过的也可以,要掌握看文档的技能。
scrapy的具体使用这里不一步一步说明了,列出几个我认为叫重要的点:
- 生成一个新的scrapy项目:
- scrapy startproject GoProxy
- scrapy.cfg是一个ini格式的配置文件,配置相关的参数可以都放在这里。
- spiders目录下放spider的代码,执行抓取的命令跟spider类名有关。例如,我的spider叫 class ProxySpider(CrawlSpider),那么我的执行命令为:
- items是一个收集抓取内容的容器,没有研究深入,在这个例子里作为传递给mongodb的过程变量使用。
- pipelines是跟外部数据接口的部分,抓取的IP内容装入items后再pipelines被存入mongodb。
关于抓取规则,这是抓取类算法的核心,足够研究很久,在这里,够用足以。
代理IP抓取没有精确性的要求,10个数据漏掉5个都没关系,所以我这里使用了宽泛的正则表达式直接过滤出IP+PORT的字符串内容。代理IP网站来源于baidu和google搜索的前6页。
这种方法个人学习够用了,要想用在其他方面,这种算法抓取到的IP数量级远远不够...0 0...(一次抓取只能过滤出2000多个IP,验证后只有大概400个有效IP)
这里贴上scapy的部分源码:proxy_spider.c
-
-
-
- import scrapy
- from scrapy.contrib.spiders import CrawlSpider, Rule
- from scrapy.contrib.linkextractors import LinkExtractor
- from bs4 import BeautifulSoup
- from GoProxy.items import GoproxyItem
-
- import re
-
- REG_IP = re.compile(r'((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))[^\d]*((\d){1,5})', re.M)
-
- class ProxySpider(CrawlSpider):
- name = "Proxy"
-
- start_urls = [
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy",
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy&pn=10",
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy&pn=20",
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy&pn=30",
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy&pn=40",
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy&pn=50",
- r"http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=ip%20proxy&pn=60",
- r"http://www.gfsoso.net/?q=ip+proxy&t=1",
- r"http://www.gfsoso.net/?q=ip+proxy&pn=10",
- r"http://www.gfsoso.net/?q=ip+proxy&pn=20",
- r"http://www.gfsoso.net/?q=ip+proxy&pn=30",
- r"http://www.gfsoso.net/?q=ip+proxy&pn=40",
- r"http://www.gfsoso.net/?q=ip+proxy&pn=50",
- r"http://www.gfsoso.net/?q=ip+proxy&pn=60",
- ]
-
- rules = (
- Rule(LinkExtractor(allow=(r'',)), callback='parse_item'),
- )
-
- def parse_item(self, response):
- soup = BeautifulSoup(response.body)
- str_list = [ tag.string or '' for tag in soup.find_all(True) ]
- body_str = ' '.join(str_list)
- items = [ GoproxyItem(ip=group[0], port=group[7], protocol='HTTP') for group in re.findall(REG_IP, body_str) ]
- return items
pipelines.c:
-
-
-
-
-
-
-
- import pymongo
- import time
- from scrapy.conf import settings
-
- class GoproxyPipeline(object):
- def __init__(self):
- connection = pymongo.MongoClient(settings['MONGODB_SERVER'], settings['MONGODB_PORT'])
- db = connection[settings['MONGODB_DB']]
- self.collection = db[settings['MONGODB_COLLECTION']]
-
- def process_item(self, item, spider):
- new_proxy = {
- "ip":item['ip'],
- "port":item['port'],
- "protocol":item['protocol'],
- }
- if self.collection.find_one(new_proxy) is None:
- self.collection.insert(new_proxy)
-
- return item
在调试完成后,用crontab把这个抓取定制为每半小时执行一次,= =保证数据库里的都是新鲜的IP~~~~。
- 0,30 * * * * cd /root/work/repos/GoProxy/&&/usr/local/bin/scrapy crawl Proxy
这样,抓取代理IP的初步工作就完成了,下一篇会简单介绍一下代理IP的验证,我使用的是daemon的形式,只要mongodb的对应collection里面有数据,就将数据去除验证,如果验证成功,则放入另一个collection,对于这个存放有效数据的collection也同样有:取出->验证->放回,的过程。至于为什么不用一个collection搞定,纯属喜好问题:)