python爬虫---爬取LOL云顶之弈数据本来是想爬取之后作最佳羁绊组合推算,但是遇到知识点无法消化(知识图谱) , 所以暂时先不组合了,实力有限
库的安装
1.requests#爬取棋子数据
2.json#棋子数据为js动态,需使用json解析
3.BeautifulSoup
实战前先新建个lol文件夹作为工作目录,并创建子目录data , 用于存放数据 。
1.爬取数据,新建个py文件,用于爬取云顶数据,命名为data.py
1.1定义个req函数,方便读取 。//需设定编码格式,否则会出现乱码
def Re_data(url):
re = requests.get(url)
re.encoding = 'gbk'
data = https://www.04ip.com/post/json.loads(re.text)
return data['data']
1.2定义个Get函数,用于读取数据并使用保存函数进行保存数据,保存格式为json 。
def Get_data():
# 获取数据并保存至data目录
base_url = ''
chess = Re_data(base_url'chess.js')
race = Re_data(base_url'race.js')
job = Re_data(base_url'job.js')
equip = Re_data(base_url'equip.js')
Save_data(chess,race,job,equip)
1.3定义save函数实现读取的数据进行文件保存,保存目录为工作目录下的data文件夹 。
def Save_data(t_chess,t_race,t_job,t_equip):
with open('./data/chess.json','w') as f:
json.dump(t_chess,f,indent='\t')
with open('./data/race.json','w') as f:
json.dump(t_race,f,indent='\t')
with open('./data/job.json','w') as f:
json.dump(t_job,f,indent='\t')
with open('./data/equip.json','w') as f:
json.dump(t_equip,f,indent='\t')
1.4定义主函数main跑起来
if __name__ == '__main__':
start = time.time()
Get_data()
print('运行时间:'str(time.time() - start)'秒')
至此 , 数据爬取完成 。
2.种族和职业进行组合 。
2.1未完成 //未完成,使用穷举方法进行组合会出现内存不够导致组合失败(for循环嵌套导致数组内存超限)
//待学习 , 使用知识图谱建立组合优?。刹慰迹?
期间遇到的问题:
1.爬取棋子数据时为动态js加载,需通过json模块的loads方法获取
2.3层for循环嵌套数据量大 , 导致计算失败,需优化计算方法 。
如何用Python做爬虫1)首先你要明白爬虫怎样工作 。
想象你是一只蜘蛛,现在你被放到了互联“网”上 。那么,你需要把所有的网页都看一遍 。怎么办呢?没问题呀,你就随便从某个地方开始,比如说人民日报的首页,这个叫initial pages,用$表示吧 。
在人民日报的首页 , 你看到那个页面引向的各种链接 。于是你很开心地从爬到了“国内新闻”那个页面 。太好了,这样你就已经爬完了俩页面(首页和国内新闻)!暂且不用管爬下来的页面怎么处理的,你就想象你把这个页面完完整整抄成了个html放到了你身上 。
突然你发现,在国内新闻这个页面上,有一个链接链回“首页” 。作为一只聪明的蜘蛛,你肯定知道你不用爬回去的吧,因为你已经看过了啊 。所以,你需要用你的脑子,存下你已经看过的页面地址 。这样,每次看到一个可能需要爬的新链接 , 你就先查查你脑子里是不是已经去过这个页面地址 。如果去过,那就别去了 。
好的 , 理论上如果所有的页面可以从initial page达到的话,那么可以证明你一定可以爬完所有的网页 。
那么在python里怎么实现呢?
很简单
import Queue
initial_page = "初始化页"
url_queue = Queue.Queue()
seen = set()
seen.insert(initial_page)
url_queue.put(initial_page)
while(True): #一直进行直到海枯石烂
if url_queue.size()0:
current_url = url_queue.get()#拿出队例中第一个的url
store(current_url)#把这个url代表的网页存储好
for next_url in extract_urls(current_url): #提取把这个url里链向的url
if next_url not in seen:
seen.put(next_url)
url_queue.put(next_url)
else:
break
写得已经很伪代码了 。
所有的爬虫的backbone都在这里 , 下面分析一下为什么爬虫事实上是个非常复杂的东西——搜索引擎公司通常有一整个团队来维护和开发 。
2)效率
如果你直接加工一下上面的代码直接运行的话,你需要一整年才能爬下整个豆瓣的内容 。更别说Google这样的搜索引擎需要爬下全网的内容了 。
问题出在哪呢?需要爬的网页实在太多太多了,而上面的代码太慢太慢了 。设想全网有N个网站,那么分析一下判重的复杂度就是N*log(N),因为所有网页要遍历一次,而每次判重用set的话需要log(N)的复杂度 。OK , OK , 我知道python的set实现是hash——不过这样还是太慢了,至少内存使用效率不高 。
通常的判重做法是怎样呢?Bloom Filter. 简单讲它仍然是一种hash的方法,但是它的特点是 , 它可以使用固定的内存(不随url的数量而增长)以O(1)的效率判定url是否已经在set中 。可惜天下没有白吃的午餐,它的唯一问题在于,如果这个url不在set中,BF可以100%确定这个url没有看过 。但是如果这个url在set中,它会告诉你:这个url应该已经出现过,不过我有2%的不确定性 。注意这里的不确定性在你分配的内存足够大的时候,可以变得很小很少 。一个简单的教程:Bloom Filters by Example
注意到这个特点 , url如果被看过,那么可能以小概率重复看一看(没关系,多看看不会累死) 。但是如果没被看过,一定会被看一下(这个很重要,不然我们就要漏掉一些网页了?。?。[IMPORTANT: 此段有问题,请暂时略过]
好,现在已经接近处理判重最快的方法了 。另外一个瓶颈——你只有一台机器 。不管你的带宽有多大,只要你的机器下载网页的速度是瓶颈的话,那么你只有加快这个速度 。用一台机子不够的话——用很多台吧!当然,我们假设每台机子都已经进了最大的效率——使用多线程(python的话,多进程吧) 。
3)集群化抓取
爬取豆瓣的时候,我总共用了100多台机器昼夜不停地运行了一个月 。想象如果只用一台机子你就得运行100个月了...
那么,假设你现在有100台机器可以用,怎么用python实现一个分布式的爬取算法呢?
我们把这100台中的99台运算能力较小的机器叫作slave,另外一台较大的机器叫作master,那么回顾上面代码中的url_queue,如果我们能把这个queue放到这台master机器上,所有的slave都可以通过网络跟master联通,每当一个slave完成下载一个网页,就向master请求一个新的网页来抓取 。而每次slave新抓到一个网页,就把这个网页上所有的链接送到master的queue里去 。同样,bloom filter也放到master上,但是现在master只发送确定没有被访问过的url给slave 。Bloom Filter放到master的内存里,而被访问过的url放到运行在master上的Redis里,这样保证所有操作都是O(1) 。(至少平摊是O(1),Redis的访问效率见:LINSERT – Redis)
考虑如何用python实现:
在各台slave上装好scrapy,那么各台机子就变成了一台有抓取能力的slave , 在master上装好Redis和rq用作分布式队列 。
代码于是写成
#slave.py
current_url = request_from_master()
to_send = []
for next_url in extract_urls(current_url):
to_send.append(next_url)
store(current_url);
send_to_master(to_send)
#master.py
distributed_queue = DistributedQueue()
bf = BloomFilter()
initial_pages = ""
while(True):
if request == 'GET':
if distributed_queue.size()0:
send(distributed_queue.get())
else:
break
elif request == 'POST':
bf.put(request.url)
好的,其实你能想到,有人已经给你写好了你需要的:darkrho/scrapy-redis · GitHub
4)展望及后处理
虽然上面用很多“简单”,但是真正要实现一个商业规模可用的爬虫并不是一件容易的事 。上面的代码用来爬一个整体的网站几乎没有太大的问题 。
但是如果附加上你需要这些后续处理,比如
有效地存储(数据库应该怎样安排)
有效地判重(这里指网页判重,咱可不想把人民日报和抄袭它的大民日报都爬一遍)
有效地信息抽?。ū热缭趺囱槿〕鐾成纤械牡刂烦槿〕隼?nbsp;, “朝阳区奋进路中华道”) , 搜索引擎通常不需要存储所有的信息,比如图片我存来干嘛...
及时更新(预测这个网页多久会更新一次)
如你所想,这里每一个点都可以供很多研究者十数年的研究 。虽然如此,
“路漫漫其修远兮,吾将上下而求索” 。
所以,不要问怎么入门 , 直接上路就好了:)
Python爬虫:想听榜单歌曲?只需要14行代码即可搞定虽然说XPath比正则表达式用起来方便,但是没有最方便,只有更方便 。我们的BeautifulSoup库就能做到更方便的爬取想要的东西 。
使用之前,还是老规矩 , 先安装BeautifulSoup库 , 指令如下:
其中文开发文档:
BeautifulSoup库是一个强大的Python语言的XML和HTML解析库 。它提供了一些简单的函数来处理导航、搜索、修改分析树等功能 。
BeautifulSoup库还能自动将输入的文档转换为Unicode编码 , 输出文档转换为UTF-8编码 。
所以,在使用BeautifulSoup库的过程中,不需要开发中考虑编码的问题,除非你解析的文档,本身就没有指定编码方式,这才需要开发中进行编码处理 。
下面,我们来详细介绍BeautifulSoup库的使用规则 。
下面,我们来详细介绍BeautifulSoup库的重点知识 。
首先,BeautifulSoup库中一个重要的概念就是选择解释器 。因为其底层依赖的全是这些解释器 , 我们有必要认识一下 。博主专门列出了一个表格:
从上面表格观察,我们一般爬虫使用lxml HTML解析器即可,不仅速度快,而且兼容性强大 , 只是需要安装C语言库这一个缺点(不能叫缺点,应该叫麻烦) 。
要使用BeautifulSoup库 , 需要和其他库一样进行导入 , 但你虽然安装的是beautifulsoup4,但导入的名称并不是beautifulsoup4,而是bs4 。用法如下:
运行之后,输出文本如下:
基础的用法很简单,这里不在赘述 。从现在开始,我们来详细学习BeautifulSoup库的所有重要知识点,第一个就是节点选择器 。
所谓节点选择器 , 就是直接通过节点的名称选择节点 , 然后再用string属性就可以得到节点内的文本,这种方式获取最快 。
比如,基础用法中,我们使用h1直接获取了h1节点,然后通过h1.string即可得到它的文本 。但这种用法有一个明显的缺点,就是层次复杂不适合 。
所以 , 我们在使用节点选择器之前,需要将文档缩小 。比如一个文档很多很大,但我们获取的内容只在id为blog的p中,那么我们先获取这个p,再在p内部使用节点选择器就非常合适了 。
HTML示例代码:
下面的一些示例,我们还是使用这个HTML代码进行节点选择器的讲解 。
这里,我们先来教会大家如何获取节点的名称属性以及内容,示例如下:
运行之后,效果如下:
一般来说一个节点的子节点有可能很多,通过上面的方式获?。荒艿玫降谝桓?。如果要获取一个标签的所有子节点 , 这里有2种方式 。先来看代码:
运行之后,效果如下:
如上面代码所示,我们有2种方式获取所有子节点,一种是通过contents属性,一种是通过children属性,2者遍历的结果都是一样的 。
既然能获取直接子节点,那么获取所有子孙节点也是肯定可以的 。BeautifulSoup库给我们提供了descendants属性获取子孙节点,示例如下:
运行之后,效果如下:
同样的,在实际的爬虫程序中,我们有时候也需要通过逆向查找父节点,或者查找兄弟节点 。
BeautifulSoup库,给我们提供了parent属性获取父节点,同时提供了next_sibling属性获取当前节点的下一个兄弟节点,previous_sibling属性获取上一个兄弟节点 。
示例代码如下:
运行之后 , 效果如下:
对于节点选择器 , 博主已经介绍了相对于文本内容较少的完全可以这么做 。但实际的爬虫爬的网址都是大量的数据 , 开始使用节点选择器就不合适了 。所以,我们要考虑通过方法选择器进行先一步的处理 。
find_all()方法主要用于根据节点的名称、属性、文本内容等选择所有符合要求的节点 。其完整的定义如下所示:
【实战】还是测试上面的HTML,我们获取name=a,attr={"class":"aaa"},并且文本等于text="Python板块"板块的节点 。
示例代码如下所示:
运行之后,效果如下所示:
find()与find_all()仅差一个all,但结果却有2点不同:
1.find()只查找符合条件的第一个节点,而find_all()是查找符合条件的所有节点2.find()方法返回的是bs4.element.Tag对象,而find_all()返回的是bs4.element.ResultSet对象
下面,我们来查找上面HTML中的a标签,看看返回结果有何不同 , 示例如下:
运行之后,效果如下:
首先,我们来了解一下CSS选择器的规则:
1..classname:选取样式名为classname的节点,也就是class属性值是classname的节点2.#idname:选取id属性为idname的节点3.nodename:选取节点名为nodename的节点
一般来说,在BeautifulSoup库中,我们使用函数select()进行CSS选择器的操作 。示例如下:
这里 , 我们选择class等于li1的节点 。运行之后,效果如下:
因为,我们需要实现嵌套CSS选择器的用法 , 但上面的HTML不合适 。这里,我们略作修改 , 仅仅更改
python 爬虫验证码(CAPTCHA)全称为全自动区分计算机和人类的公开图灵测试(Completely Automated Public Turing test to tell Computersand Humans Apart) 。从其全称可以看出 , 验证码用于测试用户是真实的人类还是计算机机器人 。
1.获得验证码图片
每次加载注册网页都会显示不同的验证验图像,为了了解表单需要哪些参数,我们可以复用上一章编写的parse_form()函数 。
import cookielib,urllib2,pprint import form REGISTER_URL = '' cj=cookielib.CookieJar() opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) html=opener.open(REGISTER_URL).read() form=form.parse_form(html) pprint.pprint(form)
{'_formkey': 'a67cbc84-f291-4ecd-9c2c-93937faca2e2', '_formname': 'register', '_next': '/places/default/index', 'email': '', 'first_name': '', 'last_name': '', 'password': '', 'password_two': '', 'recaptcha_response_field': None} 123456789101112131415161718
上面recaptcha_response_field是存储验证码的值,其值可以用Pillow从验证码图像获取出来 。先安装pip install Pillow,其它安装Pillow的方法可以参考。Pillow提价了一个便捷的Image类,其中包含了很多用于处理验证码图像的高级方法 。下面的函数使用注册页的HTML作为输入参数 , 返回包含验证码图像的Image对象 。
import lxml.html from io import BytesIO from PIL import Image tree=lxml.html.fromstring(html) print tree
Element html at 0x7f8b006ba890 img_data_all=tree.cssselect('div#recaptcha img')[0].get('src') print img_data_all
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABgCAIAAAB9kzvfAACAtklEQVR4nO29Z5gcZ5ku3F2dc865
...
rkJggg== img_data=https://www.04ip.com/post/img_data_all.partition(',')[2] print img_data
iVBORw0KGgoAAAANSUhEUgAAAQAAAABgCAIAAAB9kzvfAACAtklEQVR4nO29Z5gcZ5ku3F2dc865
...
rkJggg==binary_img_data=https://www.04ip.com/post/img_data.decode('base64') file_like=BytesIO(binary_img_data) print file_like
_io.BytesIO object at 0x7f8aff6736b0 img=Image.open(file_like) print img
PIL.PngImagePlugin.PngImageFile image mode=RGB size=256x96 at 0x7F8AFF5FAC90 12345678910111213141516171819202122232425
在本例中,这是一张进行了Base64编码的PNG图像,这种格式会使用ASCII编码表示二进制数据 。我们可以通过在第一个逗号处分割的方法移除该前缀 。然后,使用Base64解码图像数据,回到最初的二进制格式 。要想加载图像,PIL需要一个类似文件的接口 , 所以在传给Image类之前 , 我们以使用了BytesIO对这个二进制数据进行了封装 。
完整代码:
# -*- coding: utf-8 -*-form.pyimport urllibimport urllib2import cookielibfrom io import BytesIOimport lxml.htmlfrom PIL import Image
REGISTER_URL = ''#REGISTER_URL = ''def extract_image(html):
tree = lxml.html.fromstring(html)
img_data = https://www.04ip.com/post/tree.cssselect('div#recaptcha img')[0].get('src')# remove data:image/png;base64, header
img_data = https://www.04ip.com/post/img_data.partition(',')[-1]#open('test_.png', 'wb').write(data.decode('base64'))
binary_img_data = https://www.04ip.com/post/img_data.decode('base64')
file_like = BytesIO(binary_img_data)
img = Image.open(file_like)#img.save('test.png')
return imgdef parse_form(html):
"""extract all input properties from the form
"""
tree = lxml.html.fromstring(html)
data = https://www.04ip.com/post/{}for e in tree.cssselect('form input'):if e.get('name'):
data[e.get('name')] = e.get('value')return datadef register(first_name, last_name, email, password, captcha_fn):
cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
html = opener.open(REGISTER_URL).read()
form = parse_form(html)
form['first_name'] = first_name
form['last_name'] = last_name
form['email'] = email
form['password'] = form['password_two'] = password
img = extract_image(html)#
captcha = captcha_fn(img)#
form['recaptcha_response_field'] = captcha
encoded_data = https://www.04ip.com/post/urllib.urlencode(form)
request = urllib2.Request(REGISTER_URL, encoded_data)
response = opener.open(request)
success = '/user/register' not in response.geturl()#success = '/places/default/user/register' not in response.geturl()
return success12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
2.光学字符识别验证码
光学字符识别(Optical Character Recognition, OCR)用于图像中抽取文本 。本节中,我们将使用开源的Tesseract OCR引擎,该引擎最初由惠普公司开发的,目前由Google主导 。Tesseract的安装说明可以从 获取 。然后可以使用pip安装其Python封装版本pytesseractpip install pytesseract 。
下面我们用光学字符识别图像验证码:
import pytesseract import form img=form.extract_image(html) pytesseract.image_to_string(img)'' 123456
如果直接把验证码原始图像传给pytesseract , 一般不能解析出来 。这是因为Tesseract是抽取更加典型的文本,比如背景统一的书页 。下面我们进行去除背景噪音,只保留文本部分 。验证码文本一般都是黑色的,背景则会更加明亮,所以我们可以通过检查是否为黑色将文本分离出来,该处理过程又被称为阈值化 。
img.save('2captcha_1original.png') gray=img.convert('L') gray.save('2captcha_2gray.png') bw=gray.point(lambda x:0 if x1 else 255,'1') bw.save('2captcha_3thresholded.png') 1234567
这里只有阈值小于1的像素(全黑)都会保留下来,分别得到三张图像:原始验证码图像、转换后的灰度图和阈值化处理后的黑白图像 。最后我们将阈值化处理后黑白图像再进行Tesseract处理,验证码中的文字已经被成功抽取出来了 。
pytesseract.image_to_string(bw)'language'import Image,pytesseract img=Image.open('2captcha_3thresholded.png') pytesseract.image_to_string(img)'language' 123456789
我们通过示例样本测试,100张验证码能正确识别出90张 。
import ocr ocr.test_samples()
Accuracy: 90/100 1234
下面是注册账号完整代码:
# -*- coding: utf-8 -*-import csvimport stringfrom PIL import Imageimport pytesseractfrom form import registerdef main():
print register('Wu1', 'Being1', 'Wu_Being001@qq.com', 'example', ocr)def ocr(img):
# threshold the image to ignore background and keep text
gray = img.convert('L')#gray.save('captcha_greyscale.png')
bw = gray.point(lambda x: 0 if x1 else 255, '1')#bw.save('captcha_threshold.png')
word = pytesseract.image_to_string(bw)
【python爬虫函数 python爬虫例】ascii_word = ''.join(c for c in word if c in string.letters).lower()return ascii_wordif __name__ == '__main__':
main()1234567891011121314151617181920212223
我们可以进一步改善OCR性能:
- 实验不同阈值
- 腐蚀阈值文本,突出字符形状
- 调整图像大小
- 根据验证码字体训练ORC工具
- 限制结果为字典单词
python爬虫 函数返回值如何调用?在if 里只需要yield ""item_url.attrs['href']
然后Lsit(最好改可名,在python规范里,函数命名是全小写,而list又是保留字python爬虫函数,比如改为display_hrefs)只需要循环输出getUrl的结果就好python爬虫函数:
def getUrl(url: str):
....html = urlopen(url)
....for item_url in BeautifulSoup((html.read()).find ('div' , class_='AAA').findAll ("a"):
........if 'href' in item_url.attrs:
............yield ""item_url.attrs['href']
def display_hrefs(url: str):
....for href in getUrl(url):
........print(href)
if __name__ == '__main__':
....display_hrefs("")
python爬虫是干嘛的爬虫技术是一种自动化程序 。
爬虫就是一种可以从网页上抓取数据信息并保存python爬虫函数的自动化程序 , 它的原理就是模拟浏览器发送网络请求 , 接受请求响应,然后按照一定的规则自动抓取互联网数据 。
搜索引擎通过这些爬虫从一个网站爬到另一个网站,跟踪网页中的链接,访问更多的网页,这个过程称为爬行,这些新的网址会被存入数据库等待搜索 。简而言之,爬虫就是通过不间断地访问互联网,然后从中获取python爬虫函数你指定的信息并返回给python爬虫函数你 。而我们的互联网上,随时都有无数的爬虫在爬取数据,并返回给使用者 。
爬虫技术的功能
1、获取网页
获取网页可以简单理解为向网页的服务器发送网络请求,然后服务器返回给我们网页的源代码 , 其中通信的底层原理较为复杂,而Python给我们封装好了urllib库和requests库等,这些库可以让我们非常简单的发送各种形式的请求 。
2、提取信息
获取到的网页源码内包含了很多信息,想要进提取到我们需要的信息,则需要对源码还要做进一步筛选 。可以选用python中的re库即通过正则匹配的形式去提取信息,也可以采用BeautifulSoup库(bs4)等解析源代码,除了有自动编码的优势之外,bs4库还可以结构化输出源代码信息,更易于理解与使用 。
3、保存数据
提取到我们需要的有用信息后,需要在Python中把它们保存下来 。可以使用通过内置函数open保存为文本数据 , 也可以用第三方库保存为其它形式的数据,例如可以通过pandas库保存为常见的xlsx数据,如果有图片等非结构化数据还可以通过pymongo库保存至非结构化数据库中 。
python爬虫函数的介绍就聊到这里吧,感谢你花时间阅读本站内容 , 更多关于python爬虫例、python爬虫函数的信息别忘了在本站进行查找喔 。
推荐阅读
- 体育竞技游戏冠军冲刺,游戏 竞技体育
- MongoDB查询前500条数据,mongodb查询记录数
- linux中的cdo命令,linux常用命令cd怎么用
- 类似cs的网络游戏,跟cs一样的游戏叫什么
- 关于错误代码java23的信息
- 如何删除电商营销记录,如何做电商营销
- 关于棋牌游戏法规的信息
- oracle其他数据库,oracle与其他数据库的不同
- python函数运行过程 python 运行过程