玩过python爬虫的小伙伴们都知道,网站的反爬虫策略之一就是IP黑名单,也就是不能用同一个ip地址连续多次爬取一个网站的数据,爬得多了,网站的反爬虫策略就会把这个ip地址加入到黑名单中,那么除非你更换ip,否则就再也获取不到数据了,也有可能陷入爬虫陷阱或被其他反爬虫策略制裁:),所以我们需要不断的更换自己的ip地址来伪装自己,所以我们得准备一大堆代理ip。
随便google了一下免费代理,出现的第一个就是这个:免费代理
我们就使用强大的python三方库开搞吧,主要用到的有bs4,requests和
sqlite3
其中bs4和requests都是最常见的爬虫标配库,sqlite3是一个很好用的python官方库。
1.先获取目标网站的html数据
import requests # 导入
header = { # 添加header可以将程序伪装成浏览器
"Host": "www.kuaidaili.com",
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8',
}
TARGET_URL = ("http://www.kuaidaili.com/free/inha/1) # 目标地址
html = requests.get(url=TARGET_URL, headers=header, timeout=30).content # 获取html文本
print(html)
在chrome中打开目标地址,按F12,检查网页代码,可以看到我们想要的数据都在table标签的一个个tr标签中
![](https://img.haomeiwen.com/i1241767/901f62450a28a7db.png)
那么我们拿到html文本之后,只要对其进行解析和过滤,就可以拿到我们想要的数据了。
2.解析html
这里用到了强大的bs4库中的BeautifulSoup类,当然正则表达式掌握的非常熟练的同学可以直接使用正则去匹配,那样的话,效率会更高。
对BeautifulSoup不熟悉的同学,可以查看官方文档
from bs4 import BeautifulSoup# 导入三方库
soup = BeautifulSoup(html, 'lxml') # 创建一个BeautifulSoup,使用更强的lxml解析器,
# 需要提前安装
list_tr = soup.find('div', id='list').find_all('tr') # 提取id为list的div标签中的所有tr标签
for i in range(len(list_tr)): # 遍历tr标签的列表
if i == 0: continue # 因为从上图中我们可以看到第一个tr标签里面的内容是表头,
# 不是我们需要的数据,所以我们跳过第一个tr标签,从第二个tr标签开始遍历
tr = list_tr[i]
list_td = tr.find_all('td')# 获取每个tr标签中的所有td标签,分析html可知td标签从上到下
# 依次是ip,端口,匿名度等信息...
ip = list_td[0].get_text()
port = list_td[1].get_text()
anonymous = list_td[2].get_text()
types = list_td[3].get_text()
location = list_td[4].get_text()
speed = list_td[5].get_text()
verify_time = list_td[6].get_text()
# 创建代理对象,把每个代理信息都保存到对象中,这一步也可以跳过
daili = Daili(ip, port, anonymous, types, location, speed, verify_time)
3.保存数据
拿到了大量的数据之后,肯定是得保存起来,供日后使用,这里用sqlite数据库进行保存,它与mysql相比是一个更简单和轻量级的数据库,完全可以满足目前的需求。
import sqlite3
if not os.path.exists('ip.db'):# 检查数据库文件是否存在
self.create_table() # 创建数据库
conn = sqlite3.connect('ip.db')# 建立连接
cursor = conn.cursor()# 创建操作游标
sql = "INSERT INTO ip(ip,port,anonymous,types,location,speed,verify_time) VALUES (" + str(
'\'' + daili.ip + '\',\'' + daili.port + '\',\'' + daili.anonymous + '\',\'' + daili.types + '\',\'' + daili.location + '\',\'' + daili.speed + '\',\'' + daili.verify_time) + '\')'
cursor.execute(sql)# 执行sqlite语句
conn.commit()# 最后不要忘了提交操作
conn.close()
4.最后对代码进行简单的封装
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Created by master on 2017/4/7
import os
import requests
from bs4 import BeautifulSoup
import sqlite3
from Kuaidaili.FreeDaili import Daili
class KuaiDaili(object):
def get_html(self, page):
header = { # 添加header可以将程序伪装成浏览器
"Host": "www.kuaidaili.com",
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8',
}
TARGET_URL = ("http://www.kuaidaili.com/free/inha/%s" % page) # 目标地址
html = requests.get(url=TARGET_URL, headers=header, timeout=30).content # 获取html文本
return html.decode("utf-8")
def create_table(self):
conn = sqlite3.connect('ip.db')
cursor = conn.cursor()
cursor.execute(
'''CREATE TABLE ip (id INTEGER PRIMARY KEY ,
ip VARCHAR(20) ,
port BOOLEAN ,
anonymous VARCHAR(20) ,
types VARCHAR(20) ,
location VARCHAR(20) ,
speed VARCHAR(20) ,
verify_time VARCHAR(20))
''')
conn.commit()
def insert_ip(self, daili):
if not os.path.exists('ip.db'):
self.create_table() # 创建数据库
conn = sqlite3.connect('ip.db')
cursor = conn.cursor()
sql = "INSERT INTO ip(ip,port,anonymous,types,location,speed,verify_time) VALUES (" + str(
'\'' + daili.ip + '\',\'' + daili.port + '\',\'' + daili.anonymous + '\',\'' + daili.types + '\',\'' + daili.location + '\',\'' + daili.speed + '\',\'' + daili.verify_time) + '\')'
daili.__str__()
cursor.execute(sql)
conn.commit()
def ip_list(self, html):
soup = BeautifulSoup(html, 'lxml') # 创建一个BeautifulSoup,使用更强的lxml解析器,
# 需要提前安装
list_tr = soup.find('div', id='list').find_all('tr') # 提取id为list的div标签中的所有tr标签
for i in range(len(list_tr)): # 遍历tr标签的列表
if i == 0: continue # 因为从上图中我们可以看到第一个tr标签里面的内容是表头,
# 不是我们需要的数据,所以我们跳过第一个tr标签,从第二个tr标签开始遍历
tr = list_tr[i]
list_td = tr.find_all('td')# 获取每个tr标签中的所有td标签,分析html可知td标签从上到下
# 依次是ip,端口,匿名度等信息...
ip = list_td[0].get_text()
port = list_td[1].get_text()
anonymous = list_td[2].get_text()
types = list_td[3].get_text()
location = list_td[4].get_text()
speed = list_td[5].get_text()
verify_time = list_td[6].get_text()
# 创建代理对象,把每个代理信息都保存到对象中,这一步也可以跳过
daili = Daili(ip, port, anonymous, types, location, speed, verify_time)
self.insert_ip(daili)# 插入数据
def batch_insert(self, page=10):# 批量插入
for i in range(1, page):
resp = self.get_html(i)
self.ip_list(resp)
def query(self):# 查询数据
conn = sqlite3.connect('ip.db')
cursor = conn.cursor()
# sql = 'select ip,port from ip where location like "中国 江苏省 镇江市%";'
# sql = 'select * from ip where port="80";'
sql = 'select * from ip;'
rows = cursor.execute(sql)
for row in rows:
print(str(row[0]) + ":" + str(row[1]))
print('rows length:%s', len(rows))
conn.commit()
conn.close()
if __name__ == '__main__':
daili = KuaiDaili()
daili.batch_insert()# 在这里可以传入你想爬取多少页数据,默认的话是10页
最后是抓取的成果:
![](https://img.haomeiwen.com/i1241767/a8925b8ef75a0a9e.png)
总结
整个程序非常的简单,得益于python强大的三方库支持,我们可以仅仅使用几行代码就能实现想要的功能,但是建议克制使用爬虫,以免给目标网站造成巨大的服务器压力,从而影响正常的用户访问。
源码
网友评论