本文做者:魏泯html
博客源地址:https://www.cnblogs.com/simple/python
作有效率的魔法师sql
*跳转到文章结尾*
mongodb
爬虫就是 模拟浏览器发送网络请求,获取响应,按照规则提取数据的程序。爬虫要的就是保存数据,只抓取不保存毫无用处。chrome
Url:须要进行解码或转码
爬虫和浏览器请求的URL地址有必定差异。Elements与Network中的源码会不同。数据库
Http:超文本传输协议:以明文方式进行传输,效率更高。
Https:Http+SSL(安全套接字层):传输数据以前,将数据加密,以后解密,效率较低,可是更安全。json
这二者都包含请求与响应部分。浏览器
Http报文请求由三部分组成:请求行、请求头、请求体缓存
Status code:状态码
Conection: keep-alive 支持长链接
Cache-Control:max-age=0 缓存控制为零
User-Agent:浏览器(内核)身份标识
Upgrade-Insecure-Requests:支持将不安全请求转换的功能
Accept:表示我想接收什么数据,q=权重
Cookie:浏览器保存在用户本地的一些信息,包括用户密码,帐号信息,网站校验信息(例如csrf跨站保护)。会被携带发送给服务器。Cookie能够被服务器用来判断客户端是不是爬虫。
Query-String-Parameters:请求数据(GET)
From-data:请求数据(POST)
能够在Chorme中模拟多种版本的机器安全
GET请求没有请求体,数据放在URL中
POST请求有请求体:携带数据,参数放置于请求体中,经常使用于登录注册、传输大文本。
requests模块是一个第三方包:用于模拟http数据请求。
在接下来的内容里咱们学习一下它的多种请求。
requests方式比urlib方式简单
50%的动态内容是json格式的数据。
Http请求的get的请求方式:
使用这种方式获得一个响应对象
url = "http://www.baidu.com/" response = requests.get(url=url)
Terminal:
<Response [200]>
使用这种方式获得一个响应对象
url = "http://www.baidu.com/" data = {键:"值"} response = requests.get(url=url,data=data)
Terminal:
<Response [200]>
headers是一个Hash字典,以键值的方式存放头部信息。
例如:
headers={"键":"值,} response = requests.get(url=url, headers=headers)
除了url和之外还有不少参数,好比timeout、代理IP等等
配合异常捕获,在指定时间返回响应
# 在三秒内必须返回响应,不然则会报错 response = requests.get(url=url,headers=headers,timeout=3)
proxies = [{"http":"113.122.8.45:53128"},{"http":"114.122.8.45:53128"},{"http":"115.122.8.45:53128"}]
proxy = random.choice(proxies)
经过response
获取页面的响应内容,包括响应头、响应体。
这是咱们所使用的公共代码:
import requests url = 'https://www.cnblogs.com/Asterism-2012/' response = requests.get(url=url)
print(response.content)
Terminal:
b'\r\n<!DOCTYPE html>\r\n<html lang="zh-cn">\r\n<head>\r\n<meta ......略
咱们发现刚才打印的content内容是byte,为了便于观看,进行解码:
它会将content的内容解码为str
类型,也能够自行指定解码类型。
x = response.content.decode() print(type(x)) print(x)
Terminal:
<class 'str'> 略......<p>by: 魏泯</p><!--PageEndHtml Block End--></body></html>
decode()自行指定content解码类型:
x= response.content.decode('utf-8') print(type(x))
Terminal:
<class 'str'>
使用text
方法获取到的源代码,是根据HTTP 头部对响应的编码做出有根据的推测,推测的文本编码。这种方法简单经常使用,适用于大部分的网站。固然既然是推测的代码,就也有出现错误的时候,这也不要紧,到时候咱们能够经过指定编码来解决这个问题。
print(response.text)
Terminal:
略......<p>by: 魏泯</p><!--PageEndHtml Block End--></body></html>
可是有的时候即使进行了解码,也没法正常看到页面源码。形成这样的缘由是本地编码与服务器编码不统一,因此咱们要对响应回来的内容制定编码。
response.encoding = response.apparent_encoding
response.encoding=”gbk”
有时候咱们须要获取到目标站点的url,用于拼接新的url或者作保存、跳转等工做,因此就用到了response.request.url
这个方法
x = response.request.url
Terminal:
https://www.cnblogs.com/Asterism-2012/
响应的url地址,有时候会由于跳转而和请求目标地址不一致,使用response.url
方法来获取它:
x = response.url print(x)
Terminal:
https://www.cnblogs.com/Asterism-2012/
有时候咱们须要测试本身的代理IP池、Header池信息,就能够经过这个方法来动态获取头部信息进行查看
x = response.request.headers print(x)
Terminal:
{'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
x = response.headers print(x)
Terminal:
{'Date': 'Fri, 04 Jan 2019 03:53:18 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Vary': 'Accept-Encoding', 'Cache-Control': 'private, max-age=10', 'Expires': 'Fri, 04 Jan 2019 03:53:28 GMT', 'Last-Modified': 'Fri, 04 Jan 2019 03:53:18 GMT', 'X-UA-Compatible': 'IE=10', 'X-Frame-Options': 'SAMEORIGIN', 'Content-Encoding': 'gzip'}
headers = {"Referver":"URL","User-Agent":"浏览器信息","Cookie":"..."}
# Cookie字符串 CookieStr = "anonymid=jm5lz4q0wv29sz; depovince=BJ; _r01_=1; JSESSIONID=abcpoYHrUXJZa6yQOiLxw; ick_login=4c5c0781-d37e-44c5-98a7-8e3fee81d222; ick=e74b83d4-c258-4de9-bd6c-3426f777fadd; XNESSESSIONID=949847ff1bf9; jebe_key=38dc9339-f175-472f-9288-02e4e7e4b59c%7Cd931901a60720bfd1a4f2f38c98639f3%7C1537147847212%7C1%7C1537147849534; wp_fold=0; jebecookies=054ec649-ffed-4989-beda-1be907785a33|||||; _de=BA25AEE63DF6B7A91E89E9A775AD2FBD; p=5929761e2707b622b09b23f92b3c04aa8; first_login_flag=1; ln_uact=15661592012; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=aaf1d9103cf916e1d824260c832ceaf38; societyguester=aaf1d9103cf916e1d824260c832ceaf38; id=968054908; xnsid=1acd462c; ver=7.0; loginfrom=null"
# 这是一个字典生成式,生成正式使用的Cookie Cookie = {i.split("=")[0]:i.split("=")[1] for i in CookieStr.split(";")} response = requests.get(url=url,headers=headers,cookies=Cookie)
import json
Py_data = json.loads(response.text)`
Js_data = json.dumps(Py_data)
Js_data = json.dumps(Py_data,ensure_ascii=False)
Js_data = json.dumps(Py_data,indent=2)
/html/head/meta
:可以选中html下的head下的全部的meta标签//li
:当前页面全部的li标签/html/head/link//li
:表示meta下的全部li标签//div[@class="father"]//li
: 获取class名为father的div下的全部li标签//a/text()
:获取a标签中直接裸露的文本内容a//text()
:获取a下的全部文本,包括子节点文本a/@href
:获取a标签中 href属性中的内容
# 获取词语解释 w_ex = html2.xpath('//*[@id="content"]/div[2]')[0].xpath("string(.)")
@后面跟属性,若是放在方括号中,表明对所过滤的标签集合进行过滤。若是放在url后,则表明获取该属性的值
etree.HTML(response.text)
# 将响应信息编码改成网站制定编码 response.encoding = response.apparent_encoding
dir = "directory" if not os.path.exsits(dir): pass
dir = "directory" os.mkdir(dir)
with("file_name","w+",encoding="utf-8") as f: f.write(content)
# 获取返回响应信息头部,这个不是很重要 for v,j in response.headers.items(): print(v,':',j) # 获取请求信息头部 for v,j response.request.headers.items(): print(v,':',j)
headers = { 'User-Agent':'伪造的浏览器内核信息' } response = requests.get(url=url,headers=headers)
headers = { 'Referer':'伪造的 上一级URL' } response = requests.get(url=url,headers=headers)
py_date = json.loads(response.text())
# 代理IP列表 proxies = [{"http":“133.12.45.12:8564”},{"协议":"IP:端口号"}] # random随机选择列表中的一个元素生成代理 proxy = random。choice(proxies) response = requests.get(proxies=proxy)
mongod.exe --dbpath C:\data\db(路径) 指定服务地址
mongod(在环境变量下)
use DB_NAME
db.tb_name.insert({key:value})
show dbs;
db.dropDatabase()
db.createCollection("set_name")
show collections
db.collection.drop()
scrapy genspider x www.x.com
这里使用的版本是1.0以上的版本,在填写爬虫域名的时候 不须要加引号
scrapy crawl x
>>>scrapy genspider -l Available templates: basic crawl csvfeed xmlfeed
爬虫文件是整个框架中咱们最常编写的,里面包括一些内容须要咱们学习。
这里的配置有不少,但并非咱们所学的所有,譬如分布式设定,是要本身手写进去的
# Obey robots.txt rules ROBOTSTXT_OBEY = False # default:True
# Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #}
# The initial download delay #AUTOTHROTTLE_START_DELAY = 5
#ITEM_PIPELINES = { # 'Csdnboke.pipelines.CsdnbokePipeline': 300, #}
# 导入模块 from scrapy.exceptions import DropItem # 创建一个用于去重的类 class Set_it(object): # 创建一个构造方法 def __init__(self): self.set0 = set() # 创建一个process_item方法,它会自动调用 def process_item(self, item, spider): # 标题 title = item["title"] # 判断标题是否已经存入了set中 if title in self.set0: # 将这条item记录删除,而且输出一条提示信息 raise DropItem("这一条内容已经存在了,因此我把它删了:%s"%title) # 不然将标题存入 else: # self.set0.add(title) return item
newspaper是一个第三方包,用于快速抓取页面信息。它的开发团队来自于美国,如今还仍在维护当中。若是要使用,首先要保证在你的电脑上下载并安装这个包,对此,咱们可使用pip这样的包管理器进行直接下载安装,固然,用conda也能够。
pip install newspaper3k
import newspaper
# 实例化Article # demo: # news = newspaper.Article() news = newspaper.Article(url=base_url,language='zh')
news.download() news.parse()
content = news.text
title = news.title
img = news.imges
retrying是一个第三方模块,用于重试出现异常的函数。
首先进行安装:
pip install retrying (安装)
代码示例(“出事了算个人,你尽管去作,作错了也不怕,但最多三次”):
from retrying import retry # 做为装饰器 装饰函数,报错仍然重复执行,直到三次才算出错 @ retry(stop_max_attempt_number=3) def fun1(): print("hello world.") time.sleep(1) raise ValueError("This is a test error.")
#coding=utf-8 '''微型ORM v1.1 @help: 首先要保证你的items中的键值与数据库中的字段吻合,其次要本身创建库和数据表, 传入你的item,而且传入表的名称 @Form: 魏泯 ''' def sql(item,table): ''' item: Your dict. table: Your table name. ''' # 生成两个列表推导式 keylis = [key for key,values in item.items()] vlis = [values for key,values in item.items()] # 生成sql 语句中所须要的 str1215 = '"{}"'+',"{}"'*(len(item)-1) str1217 = '{}'+',{}'*(len(item)-1) str1216 = 'insert into '+table+'('+str1217+')'+' value ('+str1215+')' _sql = str1216.format(*keylis,*vlis) return _sql # 返回sql语句