经过前面的步骤,一个小巧的虫子就出炉了。下面是它的全部身子骨:
import csv
import http
import socket
import threading
import urllib
import requests
from bs4 import BeautifulSoup
class CsvSaver:
def __init__(self, path='./', filename='result.txt', method='w+'):
self.path = path
self.filename = filename
self.method = method
# 打开的文件
self.FILE = None
self.WRITER = None
def open(self):
self.FILE = open(self.path + self.filename, self.method)
self.WRITER = csv.writer(self.FILE, quoting=csv.QUOTE_ALL)
def write(self, data):
'参数是一个list'
self.WRITER.writerow(data)
self.FILE.flush()
def close(self):
self.FILE.close()
class Spider:
def __init__(self, dataSaver, failSaver=None, thread=5, timeout=2, ):
self.thread = thread
# 队列
self.queue = []
# 已经爬行过的集合
self.history = []
# 爬行数据记录
self.dataSaver = dataSaver
# 失败Log记录
self.failSaver = failSaver
# 线程们
self.THREADS = []
# 互斥锁
self.queueLock = threading.Lock()
# 带cookie的请求器
self.requester = self.login()
# 设置超时
socket.setdefaulttimeout(timeout)
def login(self):
auth_url = 'http://freedns.afraid.org/zc.php?from=L2RvbWFpbi8='
# 登录用户名和密码
loginInfo = {
'username': '[email protected]',
'password': '413431390',
'remember': 1,
'from': 'L2RvbWFpbi8=',
'action': 'auth'
}
# urllib进行编码
login_data = urllib.parse.urlencode(loginInfo).encode()
headers = {
"Host": "freedns.afraid.org",
"Connection": "keep-alive",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36",
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, sdch",
"DNT": "1",
"Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4",
"Referer": "http://freedns.afraid.org/domain/?ls=1",
}
# 初始化一个CookieJar来处理Cookie
cookieJar = http.cookiejar.CookieJar()
# 实例化一个全局opener
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cookieJar))
# 获取cookie
req = urllib.request.Request(auth_url, login_data, headers)
result = opener.open(req)
print('登录成功')
return opener
def addUrlBlock(self, start=100, end=200):
for index in range(start, end):
url = 'http://freedns.afraid.org/subdomain/edit.php?edit_domain_id=' + str(index)
self.addUrl(url)
def addUrl(self, url):
# 得到锁
self.queueLock.acquire()
if not url in self.history:
# 添加URL
self.queue.append(url)
# 释放锁
self.queueLock.release()
def getUrl(self):
while self.queue:
url = None
# 得到锁
self.queueLock.acquire()
# 获得URL
if self.queue:
url = self.queue.pop(0)
self.history.append(url)
# 释放锁
self.queueLock.release()
yield url
raise StopIteration
def findInfo(self, nowUrl, data):
status = data.find('option', value=True).text.strip()
self.dataSaver.write(status.split(' '))
def findUrl(self, nowUrl, data):
aSet = data.find_all('a')
for a in aSet:
self.addUrl(a.href)
def runThread(self):
for url in self.getUrl():
try:
# 得到想要的信息
data = BeautifulSoup(self.requester.open(url).read())
# 处理信息
self.findInfo(url, data)
print("Success %s" % url)
# 发现链接
# self.findUrl(url, data)
except:
print("Fail %s" % url)
self.failSaver.write(["Fail", url])
def run(self):
self.dataSaver.open()
if self.failSaver:
self.failSaver.open()
self.THREADS = []
# 生成线程
for i in range(self.thread):
self.THREADS.append(threading.Thread(target=self.runThread))
# 开启线程
for i in range(self.thread):
self.THREADS[i].start()
# 等待线程完成
for i in range(self.thread):
self.THREADS[i].join()
self.dataSaver.close()
if self.failSaver:
self.failSaver.close()
if __name__ == '__main__':
dataStore = CsvSaver(filename='result.csv')
logStore = CsvSaver(filename='log.csv')
spider = Spider(dataSaver=dataStore, failSaver=logStore, thread=3)
spider.addUrlBlock(300, 310)
spider.run()
print('全部完成')
诚然,这个爬虫不能与Apache Nutch或者WebMagic相比,并且功能什么的也都很弱,没有进度监控、没有自动调度,各种简陋。不过,作为练习数据结构、练习Python语法、临时有点什么体力活需要自动解决、满足自己好奇心的时候,它还是很有效的。
下面是一些爬取成果:
另外还可以把它改造成为一个图片抓取器什么的。谁会改写代码的话可以帮帮忙。
当然,有些神人还能通过抓取QQ空间啊什么的获得了TX的3000W好友关系数据。唔……大神请收下我中了一箭的膝盖。
好,本次教程就到这里,第一次写连载教程也就到这里。如果有什么建议的话,请联系我。
发表回复