一个python爬虫工具类
写了一个爬虫工具类。
# -*- coding: utf-8 -*-
# @Time : 2018/8/7 16:29
# @Author : cxa
# @File : utils.py
# @Software: PyCharm
from retrying import retry
from decorators.decorators import decorator, parse_decorator
from glom import glom
from config import headers
import datetime
import hashlib
from tomorrow import threads
from requests_html import HTMLSession
try:
import simplejson as json
except ImportError:
import json
class MetaSingleton(type):
_inst = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._inst:
cls._inst[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._inst[cls]
class Get_Proxies(metaclass=MetaSingleton):
ip = None
def getproxy(self, change_proxy):
if self.ip is None:
self.ip = self.get_ip(HTMLSession())
self.proxies = {
'http': self.ip,
'https': self.ip
}
if change_proxy:
self.ip = self.get_ip(HTMLSession())
self.proxies = {
'http': self.ip,
'https': self.ip
}
return self.proxies
def get_ip(self, session):
url = 'ip'
req = session.get(url)
if req.status_code == 200:
jsonstr = req.json()
isok = glom(jsonstr, "resCode")
if isok == "0000":
key = glom(jsonstr, ('reData', ['key']))[0]
uname = glom(jsonstr, ('reData', ['username']))[0]
passwd = glom(jsonstr, ('reData', ['password']))[0]
proxies = f"http://{uname}:{passwd}@{key}"
return proxies
@retry(stop_max_attempt_number=5, wait_random_min=3000, wait_random_max=7000)
@decorator
def post_html(session, post_url: int, post_data: dict, headers=headers, timeout=30):
'''
:param session: 传入session对象
:param post_url: post请求需要的url
:param headers: 报头信息,config模块默认提供
:param post_data: post信息 字典类型
:param timeout:
:return:
'''
post_req = session.post(url=post_url, headers=headers, data=post_data, timeout=timeout, proxies=get_proxies())
if post_req.status_code == 200:
post_req.encoding = post_req.apparent_encoding
# time.sleep(random.randint(1, 3))
return post_req
# 随机等待1-3s
@retry(stop_max_attempt_number=5, wait_random_min=3000, wait_random_max=7000)
@decorator
def get_response(session, url: str, params=None, headers=headers, timeout=10):
'''
获取response
:param url:链接
:return: return response object
'''
try:
req = session.get(url=url, headers=headers, params=params, timeout=timeout, proxies=get_proxies())
except:
req = session.get(url=url, headers=headers, params=params, timeout=timeout, proxies=get_proxies(True))
if req.status_code == 200:
req.encoding = req.apparent_encoding
# time.sleep(random.randint(1, 3))
return req
# 随机等待1-3s
@decorator
def get_html(req):
'''
获取html类型的网页格式
:param req:
:return:
'''
source = req.text
return source
@decorator
def get_json(req):
'''
获取json类型的网页格式
:param req: response对象
:return:
'''
try:
jsonstr = req.json()
except:
source = get_html(req)
if source.endswith(';'):
jsonstr = json.loads(source.replace(';', ''))
return jsonstr
@parse_decorator(None)
def get_xpath(req, xpathstr: str):
'''
xpath操作获取节点
:param req:response对象
:param xpathstr:
:return:
'''
node = req.html.xpath(xpathstr)
return node
@decorator
def get_link(node):
'''
获取当前节点的链接
:param req:response对象
:return:返回绝对链接
'''
return list(node.absolute_links)[0]
@parse_decorator(None)
def get_text(node):
'''
获取当前节点下的文本
:param req:response对象
:param xpathstr:xpath表达式
:return:
'''
return node.text
@parse_decorator(None)
def get_all_text(node):
'''
获取该节点包括其子节点下的所有文本
:param req:response对象
:param xpathstr:xpath表达式
:return:
'''
if isinstance(node, list):
return node[0].full_text
else:
return node.full_text
@decorator
def get_json_data(jsonstr: str, pat: str):
'''
#通过glom模块操作数据
:param jsonstr:json字符串
:param pat:模板
:return:
'''
item = glom(jsonstr, pat)
return item
@decorator
def get_hash_code(key):
'''
获取字符串hash值,md5加密
:param key:
:return:
'''
value = hashlib.md5(key.encode('utf-8')).hexdigest()
return value
@parse_decorator(None)
def get_next_node(node, xpathstr):
'''
当前节点下面操作xpath
:param node: 节点
:param xpathstr: xpath表达式
:return:
'''
next_node = node[0].xpath(xpathstr)
if next_node:
return next_node
@decorator
def get_datetime_from_unix(unix_time):
'''
时间戳转时间格式
:param unix_time:
:return:
'''
unix_time_value = unix_time
if not isinstance(unix_time_value, int):
unix_time_value = int(unix_time)
new_datetime = datetime.datetime.fromtimestamp(unix_time_value)
return new_datetime
def get_proxies(change_proxy=False):
ip = Get_Proxies().getproxy(change_proxy)
return ip
@decorator
@threads(20)
@retry(stop_max_attempt_number=5)
def async_get_response(session, url: str, headers=headers, timeout=10):
'''
获取response
:param url:链接
:return: return response object
'''
try:
req = session.get(url=url, headers=headers, timeout=timeout, proxies=get_proxies())
except:
req = session.get(url=url, headers=headers, timeout=timeout, proxies=get_proxies(True))
# if req.status_code==200:
# req.encoding=req.apparent_encoding
# #time.sleep(random.randint(1, 3))
return req
if __name__ == '__main__':
print(get_proxies())
以下是headers文件的内容
import random
first_num = random.randint(55, 62)
third_num = random.randint(0, 3200)
fourth_num = random.randint(0, 140)
class FakeChromeUA:
os_type = [
'(Windows NT 6.1; WOW64)', '(Windows NT 10.0; WOW64)', '(X11; Linux x86_64)',
'(Macintosh; Intel Mac OS X 10_12_6)'
]
chrome_version = 'Chrome/{}.0.{}.{}'.format(first_num, third_num, fourth_num)
@classmethod
def get_ua(cls):
return ' '.join(['Mozilla/5.0', random.choice(cls.os_type), 'AppleWebKit/537.36',
'(KHTML, like Gecko)', cls.chrome_version, 'Safari/537.36']
)
headers = {
'User-Agent': FakeChromeUA.get_ua(),
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Connection': 'keep-alive'
}
以下是logger文件的内容
# -*- coding: utf-8 -*-
import os
import time
import logging
import sys
log_dir1=os.path.join(os.path.dirname(os.path.dirname(__file__)),"logs")
today = time.strftime('%Y%m%d', time.localtime(time.time()))
full_path=os.path.join(log_dir1,today)
if not os.path.exists(full_path):
os.makedirs(full_path)
log_path=os.path.join(full_path,"t.log")
def get_logger():
# 获取logger实例,如果参数为空则返回root logger
logger = logging.getLogger("t")
if not logger.handlers:
# 指定logger输出格式
formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')
# 文件日志
file_handler = logging.FileHandler(log_path,encoding="utf8")
file_handler.setFormatter(formatter) # 可以通过setFormatter指定输出格式
# 控制台日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.formatter = formatter # 也可以直接给formatter赋值
# 为logger添加的日志处理器
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 指定日志的最低输出级别,默认为WARN级别
logger.setLevel(logging.INFO)
# 添加下面一句,在记录日志之后移除句柄
return logger
一个python爬虫工具类的更多相关文章
- python爬虫工具集合
python爬虫工具集合 大家一起来整理吧!强烈建议PR.这是初稿,总是有很多问题,而且考虑不全面,希望大家支持! 源文件 主要针对python3 常用库 urllib Urllib是python提供 ...
- 常见Python爬虫工具总结
常见Python爬虫工具总结 前言 以前写爬虫都是用requests包,虽然很好用,不过还是要封装一些header啊什么的,也没有用过无头浏览器,今天偶然接触了一下. 原因是在处理一个错误的时候,用到 ...
- 免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作简易流量爬虫
前言 我们之前的爬虫都是模拟成浏览器后直接爬取,并没有动态设置IP代理以及UserAgent标识,本文记录免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作 ...
- Android 分享一个SharedPreferences的工具类,方便保存数据
我们平常保存一些数据,都会用到SharedPreferences,他是保存在手机里面的,具体路径是data/data/你的包名/shared_prefs/保存的文件名.xml, SharedPrefe ...
- 一个python爬虫小程序
起因 深夜忽然想下载一点电子书来扩充一下kindle,就想起来python学得太浅,什么“装饰器”啊.“多线程”啊都没有学到. 想到廖雪峰大神的python教程很经典.很著名.就想找找有木有pdf版的 ...
- MinerUtil.java 爬虫工具类
MinerUtil.java 爬虫工具类 package com.iteye.injavawetrust.miner; import java.io.File; import java.io.File ...
- Python数据库工具类MySQLdb使用
MySQLdb模块用于连接mysql数据库. 基本操作 # -*- coding: utf-8 -*- #mysqldb import time, MySQLdb ...
- 我的第一个Python爬虫——谈心得
2019年3月27日,继开学到现在以来,开了软件工程和信息系统设计,想来想去也没什么好的题目,干脆就想弄一个实用点的,于是产生了做“学生服务系统”想法.相信各大高校应该都有本校APP或超级课程表之类的 ...
- python爬虫工具
一直都听说python写爬虫工具非常方便,为了获取数据,我也要写点爬虫,但是python太灵活了,不知道python爬虫要哪些框架,要了解,比如beatiful soup,scrapy, 爬虫的额主要 ...
随机推荐
- bzoj4815[CQOI2017]小Q的格子
题意 不简述题意了,简述题意之后这道题就做出来了.放个原题面. 小Q是个程序员. 作为一个年轻的程序员,小Q总是被老C欺负,老C经常把一些麻烦的任务交给小Q来处理. 每当小Q不知道如何解决时,就只好向 ...
- 【bzoj4425】[Nwerc2015]Assigning Workstations分配工作站 贪心+堆
题目描述 佩内洛普是新建立的超级计算机的管理员中的一员. 她的工作是分配工作站给到这里来运行他们的计算研究任务的研究人员. 佩内洛普非常懒惰,不喜欢为到达的研究者们解锁机器. 她可以从在她的办公桌远程 ...
- ssh-keygen的使用方法及配置authorized_keys两台linux机器相互认证
一.概述 1.就是为了让两个linux机器之间使用ssh不需要用户名和密码.采用了数字签名RSA或者DSA来完成这个操作 2.模型分析 假设 A (192.168.20.59)为客户机器,B(192. ...
- ubuntu adduser
ubuntu adduser 添加用户 hexan 到目录 /home/hexan 下.$ sudo adduser hexan -home /home/hexan 添加一个普通用户adduser [ ...
- (转)Linux GCC常用命令
1简介 2简单编译 2.1预处理 2.2编译为汇编代码(Compilation) 2.3汇编(Assembly) 2.4连接(Linking) 3多个程序文件的编译 4检错 5库文件连接 5.1编译成 ...
- Kinect实现简单的三维重建
Kinect想必大家已经很熟悉了,最近基于Kinect的创意应用更是呈井喷状态啊!看到很多国外大牛用Kinect做三维重建,其中最著名的要数来自微软研究院的Kinect Fusion了,可以看看下面这 ...
- 《Java程序设计》第8周学习总结 20165218 2017-2018-1
20165218 2017-2018-1 <Java程序设计>第8周学习总结 教材学习内容总结 第12章 java多线程机制 java中的线程 计算机在任何给定时刻只能执行一个线程,多线程 ...
- HDU 4372 Count the Buildings——第一类斯特林数
题目大意:n幢楼,从左边能看见f幢楼,右边能看见b幢楼 楼高是1~n的排列. 问楼的可能情况 把握看到楼的本质! 最高的一定能看见! 计数问题要向组合数学或者dp靠拢.但是这个题询问又很多,难以dp ...
- 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑
http://blog.csdn.net/poem_qianmo/article/details/26977557 本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog ...
- Spring MVC @CookieValue注解
@CookieValue的作用 用来获取Cookie中的值 @CookieValue参数 1.value:参数名称 2.required:是否必须 3.defaultValue:默认值 @Cookie ...