使用到的标准库有

requests	#请求网页信息
time		#调用其中的sleep()函数,对程序进行暂定,防止在短时间内抓取过于频繁导致被服务器拦截
random	#用于生成随机数, 这里用来随机生成10-30的整数,用做程序等待的时间。
bs4		#处理html页面,需要安装BeautifulSoup

安装库

pip install BeautifulSoup
pip install BeautifulSoup4

普通抓取

支持环境:亲测支持python2.7/3.6

	# -*- coding: utf-8 -*-
	import time
	import requests
	import random
	import os
	from bs4 import BeautifulSoup
	import sys

	reload(sys)
	sys.setdefaultencoding('utf-8')

	#设置要抓取的页面范围,以下为抓取1-4页。
	page_number = list(range(1,5))

	#抓取的链接
	url = 'http://www.xicidaili.com/nn/'

	#临时存储页面信息的文件
	filename = 'html.txt'

	# 通过for循环依次拼接链接
	for i in page_number:
		full_url = url + str(i)

		# 设置请求的头部信息,伪装成浏览器。
		headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4091.2 Safari/537.36'}

		# 随机等待几秒,防止抓取过于频繁被锁定。
		time.sleep(random.randint(5, 10))

		print("正在抓取第" + str(i) + "页......")

		# 通过前面拼接的链接,抓取页面信息
		r = requests.get(full_url, headers=headers)

		print("第" + str(i) + "页抓取完成!")

		# 将抓取到的页面存入临时的文件
		with open(filename, 'a') as f_obj:
			f_obj.write(r.text)

	print("开始过滤抓取的页面,请稍后......")

	# 处理前面抓取到的文件
	with open(filename) as f:

		# 通过BeaufifulSoup来处理前面抓取的html内容
		bsobj = BeautifulSoup(f.read(), 'html.parser')

		# 过滤出html页面中标题位置元素信息,
		title_list = bsobj.findAll('th')

		# 过滤出html页面中IP、端口等信息。
		ip_list = bsobj.findAll('td')

	info_list = []		

	# 对ip、端口等信息进行处理,将处理的信息也写入info中,一行一条。
	for ip_info in ip_list:
		# with open('info.txt', 'a') as f:
		text = ip_info.get_text().strip() + ' '
		if text == ' ':
			text = '填充 '
			info_list.append(text.strip())
		else:
			info_list.append(text.strip())

	print("信息过滤完成!\n开始测试代理的可用性~~~\n")

	#删除列表中的空元素
	while '' in info_list:
		info_list.remove('')

	#定义4个空列表,用来存放下面过滤出来的信息
	ip = []
	prot = []
	location = []
	type = []

	#通过while循环过滤出IP、端口、地区和类型信息	
	a = 0
	while a <= 10:
		for i in info_list[a::10]:
			if a == 1:
				ip.append(i)
			elif a == 2:
				prot.append(i)
			elif a == 3:
				location.append(i)
			elif a == 5:
				type.append(i)
			else:
				break
		a += 1

	#依次从IP、端口、地区和类型列表中取出一个值,拼接成IP:Prot
	#测试代理IP是否可用,如果可用,则写入it_works.txt文件中
	while type:
		i = ip.pop(0)
		t = type.pop(0)
		p = prot.pop(0)
		l = location.pop(0)
		url = i + ':' + str(p)

		#防止过滤的信息中有空值,只有所有值均不为空的时候才进行测试
		if i !='' and t !='' and p !='' and l !='':
			try:
				# r = requests.get('http://ip.chinaz.com/getip.aspx', proxies={'http': url}, timeout=2)
				r = requests.get('http://2018.ip138.com/ic.asp', proxies={'http': url}, timeout=2)
			except:
				pass
			else:
				#只有响应代码在200-300之间才说明该代理IP可用,才会写入指定的文件中
				if r.status_code >= 200 and r.status_code < 300:
					print(url + ' ' + l + ' 这个代理可用!')
					with open("it_works.txt", 'a') as f:
						f.write(t + '\t')
						f.write(i + '\t')
						f.write(p + '\t')
						f.write(l + '\n')
				else:
					pass	# 如果不可用或超时直接跳过
		else:
			continue	# 如果有值为空则直接处理下一组

			#删除之前存储临时页面信息的文件
	if os.path.exists(filename):
		os.remove(filename)

	print("信息过滤完成!请查看it_works.txt文件")

使用scrapy抓取

先新建一个scrapy项目,

scrapy startproject djiango_test

然后修改项目目录中items.py文件,增加如下内容

class DailiIpsItem(scrapy.Item):
	ip = scrapy.Field()
	port = scrapy.Field()
	position = scrapy.Field()
	type = scrapy.Field()
	speed = scrapy.Field()
	last_check_time = scrapy.Field()

进到spiders目录,创建一个get_xici.py

	# -*- coding: utf-8 -*-
	import scrapy
	from django_test.items import DailiIpsItem		#因为我建的项目叫djiango_test,所以导入时全称为djiango_test.items
	import pandas as pd	#csv库

	class XiciSpider(scrapy.Spider):
		name = "xici"
		allowed_domains = ["xicidaili.com"]
		start_urls = (
			'http://www.xicidaili.com/',
		)

		def start_requests(self):
			res = []
			for i in range(1, 2):
				url = 'http://www.xicidaili.com/nn/%d'%i
				req = scrapy.Request(url)
				# 存储所有对应地址的请求
				res.append(req)
			return res

		def parse(self, response):
			table = response.xpath('//table[@id="ip_list"]')[0]
			trs = table.xpath('//tr')[1:]   #去掉标题行
			items = []
			name = ['ip', 'port', 'position', 'type', 'speed', 'last_check_time']

			for tr in trs:
				pre_item = DailiIpsItem()
				pre_item['ip'] = tr.xpath('td[2]/text()').extract()[0]
				pre_item['port'] = tr.xpath('td[3]/text()').extract()[0]
				pre_item['position'] = tr.xpath('string(td[4])').extract()[0].strip()
				pre_item['type'] = tr.xpath('td[6]/text()').extract()[0]
				pre_item['speed'] = tr.xpath('td[7]/div/@title').re('\d+\.\d*')[0]
				pre_item['last_check_time'] = tr.xpath('td[10]/text()').extract()[0]
				items.append(pre_item)

			html_csv = pd.DataFrame(columns=name, data=items)
			html_csv.to_csv('xici.csv', mode='a')

最后,执行命令,启动爬虫

scrapy crawl xici

最后更新于