请初学者作为参考,不建议高手看这个浪费时间】

前两篇大概讲述了scrapy的安装及工作流程。这篇文章主要以一个实例来介绍scrapy的开发流程,本想以教程自带的dirbot作为例子,但感觉大家应该最先都尝试过这个示例,应该都很熟悉,这里不赘述,所以,将用笔者自己第一个较为完整的抓取程序作为示例作为讲解。

首先,要大规模抓取一个网站的内容,必要的资源便是代理ip这一资源,如果不使用代理ip,又追求抓取的速度,很可能会被被抓网站发现行踪并封掉抓取机,所以抓取大量可用的代理ip便是我们第一个任务。

大概这个爬虫要实现以下三个功能:

1. 抓取代理ip,端口信息

2. 验证代理ip,判断其透明性

3. 将可用的代理ip持久化到文件中以供后续抓取程序使用

http://www.cnproxy.com/ 代理服务器网便是一个很好的代理ip的来源,简单看一下,共有12个页面,页面格式相同:

http://www.cnproxy.com/proxy1.html

http://www.cnproxy.com/proxy10.html

http://www.cnproxy.com/proxyedu1.html

http://www.cnproxy.com/proxyedu2.html

准备就绪,下面正式开始:

1. 定义item,根据需求,抓取的item最后应该包含如下信息才好用:

#前4个数据为页面可以直接获取的

ip地址

端口

协议类型

地理位置

#后三个数据为pipeline中后期得到的数据,很有用

代理类型

延迟

时间戳

所以定义代码如下:

 1 # Define here the models for your scraped items
2 #
3 # See documentation in:
4 # http://doc.scrapy.org/topics/items.html
5
6 from scrapy.item import Item, Field
7
8 class ProxyItem(Item):
9 address = Field()
10 port = Field()
11 protocol = Field()
12 location = Field()
13
14 type = Field() # 0: anonymity #1 nonanonymity
15 delay = Field() # in second
16 timestamp = Field()

2. 定义爬虫

爬虫中做的主要工作就是设置初始化urls,即【种子】,【可不是那种种子~是这种种子~】

然后在默认的parse函数中使用xpath可以轻松的获得所需要的字段,比如

addresses = hxs.select('//tr[position()>1]/td[position()=1]').re('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')

可以获得ip信息的数组

locations = hxs.select('//tr[position()>1]/td[position()=4]').re('<td>(.*)<\/td>')

可以获得地理位置信息的数组

唯一有点麻烦的就是端口信息,网站站长可能想到数据会被抓取的可能,所以端口的输出使用了js输出,这确实增加了抓取的难度,scrapy和一般的爬虫是不具备浏览器的javascript解释器的,也不会执行这些js代码,所以,爬虫拿到的html代码中的端口号好没有被输出出来~

源码是这个样子

所以,一定在html的上部,会有这些‘r’的定义,不难发现

经过几次刷新,发现这些定义并不是动态的,所以就简单些,直接拿到代码中的+r+d+r+d信息,将+号替换为空,将r替换成8,d替换成0即可,所以可以声明下边这样的一个map

port_map = {'z':'3','m':'4','k':'2','l':'9','d':'0','b':'5','i':'7','w':'6','r':'8','c':'1','+':''}

具体的爬虫代码如下

 1 from scrapy.contrib.spiders import CrawlSpider, Rule
2 from scrapy.selector import HtmlXPathSelector
3 from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
4 from proxy.items import ProxyItem
5 import re
6
7 class ProxycrawlerSpider(CrawlSpider):
8 name = 'cnproxy'
9 allowed_domains = ['www.cnproxy.com']
10 indexes = [1,2,3,4,5,6,7,8,9,10]
11 start_urls = []
12 for i in indexes:
13 url = 'http://www.cnproxy.com/proxy%s.html' % i
14 start_urls.append(url)
15 start_urls.append('http://www.cnproxy.com/proxyedu1.html')
16 start_urls.append('http://www.cnproxy.com/proxyedu2.html')
17
18 def parse(self, response):
19 hxs = HtmlXPathSelector(response)
20 addresses = hxs.select('//tr[position()>1]/td[position()=1]').re('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
21 protocols = hxs.select('//tr[position()>1]/td[position()=2]').re('<td>(.*)<\/td>')
22 locations = hxs.select('//tr[position()>1]/td[position()=4]').re('<td>(.*)<\/td>')
23 ports_re = re.compile('write\(":"(.*)\)')
24 raw_ports = ports_re.findall(response.body);
25 port_map = {'z':'3','m':'4','k':'2','l':'9','d':'0','b':'5','i':'7','w':'6','r':'8','c':'1','+':''}
26 ports = []
27 for port in raw_ports:
28 tmp = port
29 for key in port_map:
30 tmp = tmp.replace(key, port_map[key]);
31 ports.append(tmp)
32 items = []
33 for i in range(len(addresses)):
34 item = ProxyItem()
35 item['address'] = addresses[i]
36 item['protocol'] = protocols[i]
37 item['location'] = locations[i]
38 item['port'] = ports[i]
39 items.append(item)
40 return items
41 ~

3. 执行pipeline,过滤并检查抓取到的代理ip,并将其持久化到文件中

一般性的校验过程我就不赘述了,直接介绍如果验证代理可用性及透明性的方法。

这需要另一个cgi程序的帮助。简单来说一个代理是否透明,就是在做中转的时候是否会将源ip放到请求包中并能够被被抓取方获取,如果能,就说明这个代理不是透明的,使用的时候就要多留意。

一般非透明代理ip会将源ip放到HTTP_X_FORWARDED_FOR字段中,为了更严谨些,另一个cgi脚本将服务器能获取到的所有跟ip有关的数据echo出来,php代码如下:

 1 <?php
2
3 echo "PROXYDETECTATION</br>";
4 echo "REMOTE_ADDR</br>";
5 var_dump($_SERVER['REMOTE_ADDR']);
6 echo "</br>";
7 echo "env_REMOTE_ADDR</br>";
8 var_dump(getenv('REMOTE_ADDR'));
9 echo "</br>";
10 echo "env_HTTP_CLIENT_IP</br>";
11 var_dump(getenv('HTTP_CLIENT_IP'));
12 echo "</br>";
13 echo "HTTP_CLIENT_IP</br>";
14 var_dump($_SERVER['HTTP_CLIENT_IP']);
15 echo "</br>";
16 echo "HTTP_X_FORWARDED_FOR</br>";
17 var_dump($_SERVER['HTTP_X_FORWARDED_FOR']);
18 echo "</br>";
19 echo "HTTP_X_FORWARDED</br>";
20 var_dump($_SERVER['HTTP_X_FORWARDED']);
21 echo "</br>";
22 echo "HTTP_X_CLUSTER_CLIENT_IP</br>";
23 var_dump($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']);
24 echo "</br>";
25 echo "HTTP_FORWARDED_FOR</br>";
26 var_dump($_SERVER['HTTP_FORWARDED_FOR']);
27 echo "</br>";
28 echo "HTTP_FORWARDED</br>";
29 var_dump($_SERVER['HTTP_FORWARDED']);
30 echo "</br>";
31
32 ?>

假设这个服务地址为http://xxx.xxx.xxx.xxx/apps/proxydetect.php

那么pipelines的代码如下

 1 # Define your item pipelines here
2 # Don't forget to add your pipeline to the ITEM_PIPELINES setting
3 # See: http://doc.scrapy.org/topics/item-pipeline.html
4 from scrapy.exceptions import DropItem
5 import re
6 import urllib
7 import urllib2
8 import time
9 import exceptions
10 import socket
11 class ProxyPipeline(object):
12 def process_item(self, item, spider):
13 port = item['port']
14 port_re = re.compile('\d{1,5}')
15 ports = port_re.findall(port)
16 if len(ports) == 0:
17 raise DropItem("can not find port in %s" % item['port'])
18 else:
19 item['port'] = ports[0]
20 #profiling the proxy
21 #detect_service_url = 'http://xxx.xxx.xxx.xxx:pppp/apps/proxydetect.php'
22 detect_service_url = 'http://xxx.xxx.xxx.xxx/apps/proxydetect.php'
23 local_ip = 'xxx.xxx.xxx.xxx'
24 proxy_ = str('http://%s:%s' % (str(item['address']), str(item['port'])))
25 proxies = {'http':proxy_}
26 begin_time = time.time()
27 timeout = 1
28 socket.setdefaulttimeout(timeout)
29 try:
30 data = urllib.urlopen(detect_service_url, proxies=proxies).read()
31 except exceptions.IOError:
32 raise DropItem("curl download the proxy %s:%s is bad" % (item['address'],str(item['port'])))
33
34 end_time = time.time()
35 if '' == data.strip():
36 raise DropItem("data is null the proxy %s:%s is bad" % (item['address'],str(item['port'])))
37 if data.find('PROXYDETECTATION') == -1:
38 raise DropItem("wrong response the proxy %s:%s is bad" % (item['address'],str(item['port'])))
39 if data.find('PROXYDETECTATION') != -1:
40 if data.find(local_ip) == -1:
41 item['type'] = 'anonymity'
42 else:
43 item['type'] = 'nonanonymity'
44 item['delay'] = str(end_time - begin_time)
45 item['timestamp'] = time.strftime('%Y-%m-%d',time.localtime(time.time()))
46
47 #record the item info
48 fp = open('/home/xxx/services_runenv/crawlers/proxy/proxy/data/proxies.txt','a')
49 line = str(item['timestamp']) + '\t' + str(item['address']) + '\t' + str(item['port']) + '\t' + item['type'] + '\t' + str(item['delay']) + '\n'
50 fp.write(line)
51 fp.close()
52 return item

其中local_ip为抓取服务器本机的ip地址

4. 最后一个要说的就是setting.py配置文件,大家看具体代码吧

 1 # Scrapy settings for proxy project
2 #
3 # For simplicity, this file contains only the most important settings by
4 # default. All the other settings are documented here:
5 #
6 # http://doc.scrapy.org/topics/settings.html
7 #
8
9 BOT_NAME = 'proxy'
10 BOT_VERSION = '1.0'
11
12 SPIDER_MODULES = ['proxy.spiders']
13 NEWSPIDER_MODULE = 'proxy.spiders'
14 USER_AGENT = '%s/%s' % (BOT_NAME, BOT_VERSION)
15
16 DOWNLOAD_DELAY = 0
17 DOWNLOAD_TIMEOUT = 30
18
19 ITEM_PIPELINES = [
20 'proxy.pipelines.ProxyPipeline'
21 ]
22 CONCURRENT_ITEMS = 100
23 CONCURRENT_REQUESTS_PER_SPIDER = 64
24 CONCURRENT_SPIDERS = 128
25
26 LOG_ENABLED = True
27 LOG_ENCODING = 'utf-8'
28 LOG_FILE = '/home/xxx/services_runenv/crawlers/proxy/proxy/log/proxy.log'
29 LOG_LEVEL = 'DEBUG'
30 LOG_STDOUT = False

最后秀一下抓取到的代理ip数据

好了,这篇就这些,下一篇将介绍如果使用代理ip作为媒介,放心的去大规模抓取网站数据,晚安。

喜欢一起简单,实用的东西,拒绝复杂花哨,我不是GEEK.

【scrapy】使用方法概要(三)(转)的更多相关文章

  1. 编写高质量JS代码的68个有效方法(三)

    [20141030]编写高质量JS代码的68个有效方法(三) *:first-child { margin-top: 0 !important; } body>*:last-child { ma ...

  2. scrapy爬虫学习系列三:scrapy部署到scrapyhub上

    系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...

  3. python练习题-简单方法判断三个数能否组成三角形

    python简单方法判断三个数能否组成三角形 #encoding=utf-8 import math while True: str=raw_input("please input thre ...

  4. Python3 Scrapy 安装方法

    Python3 Scrapy 安装方法 (一脸辛酸泪) 写在前面 最近在学习爬虫,在熟悉了Python语言和BeautifulSoup4后打算下个爬虫框架试试. 没想到啊,这坑太深了... 看了看相关 ...

  5. centos LB负载均衡集群 三种模式区别 LVS/NAT 配置 LVS/DR 配置 LVS/DR + keepalived配置 nginx ip_hash 实现长连接 LVS是四层LB 注意down掉网卡的方法 nginx效率没有LVS高 ipvsadm命令集 测试LVS方法 第三十三节课

    centos   LB负载均衡集群 三种模式区别 LVS/NAT 配置  LVS/DR 配置  LVS/DR + keepalived配置  nginx ip_hash 实现长连接  LVS是四层LB ...

  6. js replace 全局替换 以表单的方式提交参数 判断是否为ie浏览器 将jquery.qqFace.js表情转换成微信的字符码 手机端省市区联动 新字体引用本地运行可以获得,放到服务器上报404 C#提取html中的汉字 MVC几种找不到资源的解决方式 使用Windows服务定时去执行一个方法的三种方式

    js replace 全局替换   js 的replace 默认替换只替换第一个匹配的字符,如果字符串有超过两个以上的对应字符就无法进行替换,这时候就要进行一点操作,进行全部替换. <scrip ...

  7. List的remove()方法的三种正确打开方式

    转: java编程:List的remove()方法的三种正确打开方式! 2018年08月12日 16:26:13 Aries9986 阅读数 2728更多 分类专栏: leetcode刷题   版权声 ...

  8. uni-app&H5&Android混合开发三 || uni-app调用Android原生方法的三种方式

    前言: 关于H5的调用Android原生方法的方式有很多,在该片文章中我主要简单介绍三种与Android原生方法交互的方式. 一.H5+方法调用android原生方法 H5+ Android开发规范官 ...

  9. Python 数据类型常用的内置方法(三)

    目录 Python 数据类型常用的内置方法(三) 1.列表内置方法 1.sort():升序 2.reverse():颠倒顺序 3.列表比较运算 2.字典内置方法 1.对Key的操作 2.len( )- ...

随机推荐

  1. 利用vw+rem实现移动web适配布局

    基本概念 1.单位 Px(CSS pixels) 像素 (px) 是一种绝对单位(absolute units), 因为无论其他相关的设置怎么变化,像素指定的值是不会变化的 其实是相对于某个设备而言的 ...

  2. TDictionary 与 TObjectDictionary

    TDictionary 与 TObjectDictionary 的区别是 : TObjectDictionary 可以做到 free的时候 里面的对象 一并free,从而不会出现内存 泄露. 用途: ...

  3. 虚拟机的安装以及Linux的学习

    安装虚拟机 对虚拟机的认识 其实初中的时候我就听说过虚拟机这个名词,当时的我还小,也不知道虚拟机是个什么东西,那时我傻傻的认为虚拟机只不过是电脑中的一个虚拟的计算机,没有什么实在的作用.后来随着大学课 ...

  4. HttpService与WebService的差异

    httpservice通过post和get得到你想要的东西webservice就是使用soap协议得到你想要的东西,相比httpservice能处理些更加复杂的数据类型 当你要调用一个你本服务的内容的 ...

  5. sql server2014 企业版 百度云下载

    sql server2014 企业版 百度云下载 链接: https://pan.baidu.com/s/1j7a6RWwpvSzG-sF7Dnexfw 提取码: 关注公众号[GitHubCN]回复获 ...

  6. drools7 (三、kmodule 介绍)

    注意几点: 1. kmodule 有默认的加载路径, 看  KieModuleModelImpl 这个类的源代码 public class KieModuleModelImpl implements ...

  7. USACO 6.2 Packing Rectangles

    Packing RectanglesIOI 95 The six basic layouts of four rectangles Four rectangles are given. Find th ...

  8. TestNG入门到...

    目录 一.概述 二.@Test注解常用参数 三.测试中常用的断言(assert) 四.TestNG常用注解及使用 五.配置文件xml常用标签 六.参数传递 七.测试报告 一.概述 1.TestNG是一 ...

  9. Jersey入门一:从Maven Archetype创建jersey项目

    1.用Ctrl+空格调出Spotlight搜索,输入ter调出终端窗口  2.在终端窗口进入将创建jersey项目的目录:  3.输入如下命令,创建一个名为的simple-service项目: m ...

  10. centos7 安装 supervisor

    一.安装 supervisor yum install python-setuptools easy_install supervisor 如果easy_install不好使就从官方下载: wget ...