初识python及数据爬取

初识python

作为一位前端开发人员,一直以来,接触最多的也都是html,css,js;有时候会需要搭建一些node服务器,写一些node后台代码,仅此而已;

而python,只是在以前使用某些软件时,需要python环境,就安装到了电脑,然后,从来都没有真正的接触过它;

随着数据分析、深度学习、机器学习的发展,也让我开始了python的学习之旅;虽然都说,不管是什么语言,基本上都是相通的;但是对于一种你从未接触过的语言,基础,还是非常重要的;所以,我还是默默的打开了浏览器,在百度中搜索了“python基础教程”,最后找到了Python 基础教程 | 菜鸟教程,在这里面,有环境的搭建、基本语法、数据类型、常用函数等非常基础的教程,我觉得非常适合我这种从来没有接触过的人;随后,我花了几个小时的时间,将这里面基础教程的所有内容看了一遍,在看的过程中,也跟着做了一些练习;

虽然说,看了基础教程,也顶多你大概能够使用python进行一些简单的运算而已;而作为开发人员,都明白一个道理,最好、最快的学习一种语言的方式当然是从一个简单的项目开始,自己能够从头开始做一个自己觉得有意思但是难度不是很大的东西,这样,不仅能够让自己能够更快的去理解这种语言,而且,会使自己更有学习的动力和信心;因此,我开始了一个简单的网站的数据爬取的实现,因为对于我这种前端出生的人来说,与浏览器打交道,与网页打交道,相对来说,简单很多;

开始

首先,我肯定不知道从何处开始,因此,我只能继续百度“python 爬虫”;最后找到了这篇文章“Python爬虫实战二之爬取百度贴吧帖子”,为什么选择它呢?只有一个原因,在它的文章最后,有完整的代码,我没去看里面的描述,而是,直接用sublime直接创建了一个名为

$ pachong.py

的文件,然后将代码全部拷贝进去(虽然说可能代码根本运行不通);

随后,我开始了我的爬虫之旅,一开始,我就直接在拷贝的代码基础上直接修改,而不同的是它爬取的是百度贴吧,我爬取的是汽车之家。然后代码就在这儿pachong.py(由于代码较多,就不直接贴出来了,有兴趣的,可以直接点链接进github查看);在这里面有个很坑的地方,它的所有筛选自己需要数据的方式是通过正则匹配的方式实现的,而我什么也不知道的跟着学着,也使用正则,让我为了从整个html中筛选自己需要的,花费了太多的时间,而且效果一般;但是后面才发现,已经有很完善的专门匹配页面内容方式的Python库BeautifulSoup(这是它的中文文档链接);

使用BeautifulSoup重写

当发现了BeautifulSoup之后,简单看了一篇BeautifulSoup教程,看完之后,如获至宝,因为它的使用方式里面有很多和前端里面去获取元素,获取节点有异曲同工之妙;而我最喜欢使用的,是里面的“CSS选择器”方式,简直和前端使用jquery一模一样,比如:

通过标签名查找

print soup.select('p')

通过类名查找

print soup.select('.sister')

通过 id 名查找

print soup.select('#link1')

......等等;

因此,我果断选择使用BeautifulSoup对上面最初的版本进行重写,尤其是在对内容的筛选;而这一次,我选择了去爬取“蚂蜂窝”的游记;

作为前端开发的我,对于Chrome DevTools的使用,简直是易如反掌;所以很容易就可以找出怎么去获取自己需要的内容(到底是用类名查找还是id查找,或者是什么组合查找),对于Chrome DevTools不是很熟的同学,可以看下这个感觉挺全的;

以爬取蚂蜂窝的游记为例,比如这一篇

1、通过request获取网页

request = urllib2.Request('http://www.mafengwo.cn/i/6958115.html')
response = urllib2.urlopen(request)
soup = BeautifulSoup(response.read().decode('utf8').encode('utf8'), "html.parser")

2、获取标题

return soup.select('.headtext')[0].string

3、获取文章html内容

article = soup.select('.vc_article')[0]
html = article.prettify()

4、获取用户信息(如头像,名称),这个稍微要复杂一些,因为它在上面第一步直接请求的html页面里面是找不到的,然后通过Chrome DevTools中的Network功能,可以找到拉取这些信息的请求地址“https://www.mafengwo.cn/note/pagelet/pagelet/headOperateApi?callback=jQuery1810173556954190627_1492868085919&params=%7B%22iid%22%3A%226958115%22%7D&_=1492868086249”,细心的你可能会发现,在这个请求中有个“6958115”,这个不就是第一步里面页面的结尾数字吗,我们可以理解为id;那么,这个请求就是通过

开始

https://www.mafengwo.cn/note/__pagelet__/pagelet/headOperateApi?callback=jQuery1810173556954190627_1492868085919&params=%7B%22iid%22%3A%226958115%22%7D&_=1492868086249](https://www.mafengwo.cn/note/__pagelet__/pagelet/headOperateApi?callback=jQuery1810173556954190627_1492868085919&params=%7B%22iid%22%3A%22

加上 id

6958115

加上结尾

%22%7D&_=1492868086249

最后组合成的一个完整的url,然后通过第一步请求后,将获取的数据通过正则的方式,只去html部分,然后通过BeautifulSoup取出对应的头像,姓名;

//其中article_id就是上面说的第一步链接结尾数字“6958115”
userInfoURL = 'https://www.mafengwo.cn/note/__pagelet__/pagelet/headOperateApi?callback=jQuery1810173556954190627_1492868085919&params=%7B%22iid%22%3A%22' + article_id +'%22%7D&_=1492868086249'

request = urllib2.Request(userInfoURL)
response = urllib2.urlopen(request)
result = response.read()

pattern = re.compile('jQuery.*?\(')
pattern1 = re.compile('\)\;')

result = re.sub(pattern, "", result)
result = re.sub(pattern1, "", result)

result = eval(result)

html = result['data']['html']

soup = BeautifulSoup(html, "html.parser")

//头像
avatar = soup.select('.per_pic img')[0]['src']

//用户名
name = soup.select('.per_name')[0]['title'].encode('utf-8')

搭建服务器

在你爬取到数据之后,你总会希望能够在界面上能够真正的展示出来,所以,我就决定使用python搭建一个简单的本地服务器;因为通过学习python的时候发现菜鸟教程确实比较适合我这种菜鸟的,所以就看完了Django 菜鸟教程,这个教程虽然简单,但是全面,对我做一个简单服务器来说,足够了;然后,就通过这个教程搭建了一个简单的python服务器,在浏览器中,就可以看到自己爬取的页面了,具体可见整个项目代码

mongodb 数据保存、使用

在你爬取一篇过后,肯定是不会停止的,所以,我们总会找个能够保持我们爬取数据的地方(数据库);因为以前在进行node开发的时候,使用过mongodb,所以就选择了它作为我保存数据的地方;使用python来操作mongodb,我没有找到相关比较好的文章,所以就直接参考的PyMongo 3.4.0 documentation这个api文档,这个夜比较详细和简单,对于我来说够用了;它包含了如何和mongodb链接、如何获取数据库,如何获取数据库里面的collection,如何查找、添加数据等等;其实很简单:

from pymongo import MongoClient
import settings

#连接mongodb
client=MongoClient('mongodb://127.0.0.1:27017/')

//获取数据库
db = client[settings.DBNAME]

// 获取数据库里面的collection
def getCollection(collection):
    if(collection):
        return db[collection]
    else:
        return None 

数据保存的代码就不贴出来了,有兴趣可以看这个models.py.

自动爬取所有游记

当你想爬取更多的时候,你肯定不希望是自己手动去查找一个一个的id,然后手动爬取,所以,我们就希望有更加自动化的爬取方式;对于这种方式,必须得解决下面两个问题:

  • 获取所有的游记id(就形如“6958115”这种的东西)
  • 解决因为自动化请求过快,过于频繁,导致“服务器拒绝访问”的问题

第一个,获取所有id;当你使用Chrome DevTools Network去看列表下一页的请求的时候,你会发现,它访问了一个“http://www.mafengwo.cn/note/pagelet/pagelet/recommendNoteApi?callback=jQuery18103478581123017468_1492999122522&params=%7B%22type%22%3A0%2C%22objid%22%3A0%2C%22page%22%3A1%2C%22ajax%22%3A1%2C%22retina%22%3A0%7D&_=1492999206862”这样的链接,它也是和上面获取用户信息一样分成三个部分,其中有个第几页的参数“page=1”,这里面就返回了所有的列表的html代码,其中包括我们需要的id;

url = 'http://www.mafengwo.cn/note/__pagelet__/pagelet/recommendNoteApi?callback=jQuery18103478581123017468_1492999122522&params=%7B%22type%22%3A0%2C%22objid%22%3A0%2C%22page%22%3A'+str(page)+'%2C%22ajax%22%3A1%2C%22retina%22%3A0%7D&_=1492999206862'

request = urllib2.Request(url)
response = urllib2.urlopen(request)
result = response.read()

pattern = re.compile('jQuery.*?\(')
pattern1 = re.compile('\)\;')

result = re.sub(pattern, "", result)
result = re.sub(pattern1, "", result)
result = eval(result)

html = result['data']['html']
html = html.replace('\\/', '/')
html = html.decode('string-escape')
soup = BeautifulSoup(html, "html.parser")

links = soup.select('.tn-item .tn-image a')
_ids = []

for link in links:
    _id = link['href'].replace('/i/', '').replace('.html', '')
    _ids.append(_id)

然后我们就会根据每一页获取的id循环自动跑爬取对应页面数据并保存至数据库,每跑完一页的数据,就会递归跑下一页数据,直到最后一页

只是在跑的过程中,就会遇到第二个问题,因为访问过快、过于频繁而导致服务器拒绝访问,在这儿我没有通过网上说的各种高端的方式,而是采用的比较笨重的方式,就是在跑完一个请求后,让程序休息几秒钟,再去进行下一个请求,我将时间设置的10秒,目前没有拒绝访问的问题,只是跑起来比较慢一些;

import time

.....
time.sleep(10)
.....

对于上面的所有代码,如果感兴趣的,整个项目代码可以在这儿(github)找到.

目前,爬取就差不多只有这些,后面会慢慢继续去完善和学习;对于我来说,python的学习之路也才刚刚开始;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,061评论 25 707
  • 声明:本文讲解的实战内容,均仅用于学习交流,请勿用于任何商业用途! 一、前言 强烈建议:请在电脑的陪同下,阅读本文...
    Bruce_Szh阅读 12,700评论 6 28
  • 我叔叔来信了,说是找我借钱? 他这么有钱,一个大商人,都快进福布斯排行榜的人,找我借钱?难道是破产了? 他说的很明...
    予墨读书阅读 105评论 0 0
  • 走出一身汗 回家 越来越喜欢流汗的感觉 朋友小聚完 继续走坝 此时 没有什么人 除了一两对黑暗中紧拥的情侣 除了一...
    撞墙的豆腐阅读 377评论 0 0
  • 那一潭汹涌的真心实意, 在念念不忘中丢了执着, 曾经相融进生命的风景, 在人来人往中淡了视线, 捧起的流沙散落了,...
    蛋蛋妮儿阅读 405评论 0 0