300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > python 爬虫3 新浪微博 爬虫 实战

python 爬虫3 新浪微博 爬虫 实战

时间:2022-05-26 14:48:28

相关推荐

python 爬虫3 新浪微博 爬虫 实战

这次的项目 和文件都放到了 github 上/poiu1235/weibo-catch:

有兴趣的可以follow一下,或者点个赞咯

我这里采用的深度挖掘的方式:没有设定爬取的边界(这个以后是要考虑的)

大致的思路是,用自己的 账号登陆后,获取自己的微博列表和朋友列表。

然后根据朋友列表然后在爬取对方的微博列表和朋友列表。这样不断的深度挖掘和遍历的过程

过程中我采用了mysql 数据库进行存储,后面会加入mongodb 数据库进行存储。

先补充一点linux的知识:系统里那些文件夹都按照什么功能分类的:

/bin

bin是binary的缩写。这个目录沿袭了UNIX系统的结构,存放着使用者最经常使用的命令。例如cp、ls、cat,等等。

/boot

这里存放的是启动Linux时使用的一些核心文件。

/dev

dev是device(设备)的缩写。这个目录下是所有Linux的外部设备,其功能类似DOS下的.sys和Win下的.vxd。在Linux中设备和文件是用同种方法访问的。例如:/dev/hda代表第一个物理IDE硬盘。

/etc

这个目录用来存放系统管理所需要的配置文件和子目录。

/home

用户的主目录,比如说有个用户叫wang,那他的主目录就是/home/wang也可以用~wang表示。

/lib

这个目录里存放着系统最基本的动态链接共享库,其作用类似于Windows里的.dll文件。几乎所有的应用程序都须要用到这些共享库。

/lost+found

这个目录平时是空的,当系统不正常关机后,这里就成了一些无家可归的文件的避难所。对了,有点类似于DOS下的.chk文件。

/mnt

这个目录是空的,系统提供这个目录是让用户临时挂载别的文件系统。

/proc

这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。也就是说,这个目录的内容不在硬盘上而是在内存里。

/root

系统管理员(也叫超级用户)的主目录。作为系统的拥有者,总要有些特权啊!比如单独拥有一个目录。

/sbin

s就是Super User的意思,也就是说这里存放的是系统管理员使用的管理程序。

/tmp

这个目录不用说,一定是用来存放一些临时文件的地方了。

/usr

这是最庞大的目录,我们要用到的应用程序和文件几乎都存放在这个目录下。其中包含以下子目录;

/usr/X11R6

存放X-Window的目录;

/usr/bin

存放着许多应用程序;

/usr/sbin

给超级用户使用的一些管理程序就放在这里;

/usr/doc

这是Linux文档的大本营;

/usr/include

Linux下开发和编译应用程序需要的头文件,在这里查找;

/usr/lib

存放一些常用的动态链接共享库和静态档案库;

/usr/local

这是提供给一般用户的/usr目录,在这里安装软件最适合;

/usr/man

man在Linux中是帮助的同义词,这里就是帮助文档的存放目录;

/usr/src

Linux开放的源代码就存在这个目录,爱好者们别放过哦!

/var

这个目录中存放着那些不断在扩充着的东西,为了保持/usr的相对稳定,那些经常被修改的目录可以放在这个目录下,实际上许多系统管理员都是这样干的。顺带说一下系统的日志文件就在/var/log目录中。

爬取微博规则

整个过程我想要爬取两个方面的内容。

一个是微博内容

另一个是朋友(他关注的人,主动,兴趣强烈)关系而不是(关注他的人,粉丝,被动,干扰太多)

爬取下来的话我也打算存在两个地方,一个是mysql 关系数据库里,另一个是以文本文件的形式存到系统

mysql 用的是之前hadoop 系统 里namenode 节点 里的mysql ,ip是192.168.1.113

因为默认mysql 安装时,是绑定本地ip的,就是只限定本地访问,单机访问

所以要更改配置

sudo nano /etc/mysql/f找到bind-address = 127.0.0.1

注释掉这行,如:#bind-address = 127.0.0.1

允许任意IP访问;

这样注释以后,本地访问就不能省略了 必须用-h 命令 指定主机地址

重启 MySQL:sudo /etc/init.d/mysql restart

授权用户能进行远程连接

grant all privileges on *.* to root@"%" identified by "password" with grant option;

flush privileges;

第一行命令解释如下,*.*:第一个*代表数据库名;第二个*代表表名。这里的意思是所有数据库里的所有表都授权给用户。root:授予root账号。“%”:表示授权的用户IP可以指定,这里代表任意的IP地址都能访问MySQL数据库。“password”:分配账号对应的密码,这里密码自己替换成你的mysql root帐号密码。

第二行命令是刷新权限信息,也即是让我们所作的设置马上生效。

登陆mysql 用 mysql -uroot -p

如果是登陆其他机器上的mysql 用 mysql -uroot -h192.168.1.113 -p

#查看编码方式

show variables like "character%";

#修改编码方式

sudo service mysql stop

sudo nano /etc/mysql/f

#在文件内的[mysqld]下增加如下两行设置:

character_set_server=utf8

init_connect='SET NAMES utf8'

sudo service mysql start

数据库字符集和 服务器字符集就会变成utf-8 了,就可以写中文了

这里我在ubuntu上安装的mysql 辅助工具是workbench 还有heidisql 网上不推荐navicat 虽然我在windows 下用navicat 最顺手

默认的mysql目录下data里面的'mysql'这个schema没有在workbench里面看到吧?

点击菜单-Edit->Preferences里面的SQL Editor,然后把"show Data Dicrionaries and Internal Schemas"前面的复选框给勾上,

再回过去刷新或者重新连接,就会出现了

接下来就是一些建库,建表的工作了

execute中要使用对等格式 如 name(char), age(int),此时语句为: cur.execute("insert into db.table(name,age) values(%s,%d)" % (v[name], v[age]) ,v[name]为字符,v[age]为int

executemany中不需要强制格式,同上表语句为:

values=[("zhan",23),("li",33)]

executemany("insert into db.tables(name,age) values(%s,%s)",values)

具体原因我也不清楚,只能说是走过的坑吧,executemany一般只用%s即可,用其它的可能会报错。插入后的值是正常的(貌似是自动匹配列属性?),有大侠知道的也望指教

注意: cursor.execute()可以接受一个参数,也可以接受两个参数:

(1) cursor.execute("insert into resource(cid,name) values(%s, %s)" , (12,name) );

这种格式是接受两个参数,MySQLdb会自动替你对字符串进行转义和加引号,不必再自己进行转义,执行完 此语句之后,resource表中多了一条记录: 12 \

(2) cursor.execute("insert into resource(cid,name) values(%s, %s)" % (12,name) );

这种格式是利用python的字符串格式化自己生成一个query,也就是传给execute一个参数,此时必须自己对 字符串转义和增加引号,即上边的语句是错误的,应该修改为:

name = MySQLdb.escape_string(name);

cursor.execute("insert into resource(cid,name) values(%s, '%s')" % (12,name) );

这样插入的记录才和(1)一样:12 \

create database weibocatch;use weibocatch;/*汉字和一个字母都是一个字符*/create table w_user(wid char(10) primary key,wname varchar(100) not null,recon tinyint(1), #0表示未认证,1表示已认证color tinyint(1) default null,#0表示黄v(个人),1表示蓝v(企业)flag tinyint(2) default 0, #0表示未被爬取,1表示爬取成功,2表示爬取失败inserttime timestamp default NOW());create table w_error(wid char(10),exception varchar(2000));create table w_relation(wid char(10),wfriendid char(10));create table w_conn(weiboid char(32),tag tinyint(1),/*判断是转发的微博还是原创的微博,1是转发,0是原创*/atid char(10),atname varchar(100),primary key (weiboid,tag));/*Date或DateTime类型是不能使用函数作为默认值的,所以改用timestamp类型*/create table w_content(weiboid char(32) primary key,wid char(10),content varchar(1000),url varchar(1000),map varchar(200),label varchar(100),intime varchar(100),picid int,wfrom varchar(100),inserttime timestamp default NOW());/*Date或DateTime类型是不能使用函数作为默认值的,所以改用timestamp类型*/create table w_transfer(weiboid char(32) primary key,wid char(10),transferid char(10),content varchar(1000),remark varchar(1000),label varchar(100),url varchar(1000),intime varchar(100),picid int,wfrom varchar(100),inserttime timestamp default NOW());create table pic_reg(id int primary key auto_increment,path varchar(3000),label1 varchar(100),label2 varchar(100),label3 varchar(100),title varchar(9000))auto_increment=10000;INSERT INTO weibocatch.w_user(wid,wname,recon,color,flag)VALUES('2468833122','poiu1235',0,'',0);INSERT INTO weibocatch.w_user(wid,wname,recon,color,flag)VALUES('2430104687','江森开根号',0,0,0);SHOW GLOBAL VARIABLES LIKE 'auto_incre%'; -- 全局变量select * from weibocatch.w_relation;select NOW();delete from weibocatch.pic_reg;delete from weibocatch.w_transfer;alter table weibocatch.pic_reg AUTO_INCREMENT=10000;select * from weibocatch.w_user;update weibocatch.w_user set flag=0 where wid ='2430104687'

insert 和 update 操作完成后一定要 mit(),不然不会改变数据库的

try:xxxx;except Exception as err:self.conn.rollback()print errfinally:#关闭连接,释放资源cursor.close();self.conn.close()

if(wconn.tag.strip()):#判断字符串不为空

把准备数据库连接的过程写在一个函数里,这样每次临时要用在临时去调用

self.inition()#因为mysql 连接很容易超时就断开了,默认10s,所以索性每次都用的时候在申明

#插入一条记录 全部用%s作占位符号,即使是数字也不要用%d

#因为这个插件程序会帮你转换的,字符串会自动给你加'',如果数字不会加

#使用这函数向一个给定Connection对象返回的值是该Connection对象产生#对影响AUTO_INCREMENT列的最新语句第一个AUTO_INCREMENT值的。#这个值不能被其它Connection对象的影响,即它们产生它们自己的AUTO_INCREMENT值。#第二、LAST_INSERT_ID 是与table无关的,#如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID返回表b中的Id值。cursor.execute("SELECT LAST_INSERT_ID()")#"只获取一条记录:" result = cursor.fetchone();#这个返回的是一个tuple,一个元素的元组后面都会跟一个”,“。没实际意义

#表示从第二个取到倒数第二个,去掉模式串中两头的单引号loginweb=loginweb[1:-1]

#reload(sys) #sys.setdefaultencoding( "utf-8" )#这个是因为插件报错,但是程序正常。

#str1.decode('gb2312'),表示将gb2312编码的字符串str1转换成unicode编码#str2.encode('gb2312'),表示将unicode编码的字符串str2转换成gb2312编码。

#设置读取目录是当前目录#但是虽然存文件方便了,但是由于当前路径变化导致不能正确读取当前cookies文件路径#os.chdir("/home/luis/workspace/weibo-catch/picture/")#os.getcwd()<pre name="code" class="python">#所以直接写完整路径会省去很多麻烦ppth="/home/luis/workspace/weibo-catch/picture/"

data = urllib.urlopen(picurl).read()f = open(name,'wb',8192)#设置文件缓冲区为8M大小,有的图片较大怕一次存不完f.write(data)f.close#close 方法相当于把缓冲区flush后再关闭的。

#因为f.read()方法读到的是str类型,默认是utf8, 可以直接用str类型进行查找,不用进行转码decode操作

if(countt==10):subprocess.call("pause",shell=True)#让程序暂停替换了os.system('pause')方法 或者用if(raw_input()): pass

#注意每个beautifulsoup对象截取出来的对象都是”特定的标签“对象,可以直接进行beautifulsoup相关操作#而不是字符串类型,如果要进行一些字符串操作,必须要转成str() 类型。#Beautiful Soup用了 编码自动检测 子库来识别当前文档编码并转换成Unicode编码#通过Beautiful Soup输出文档时,不管输入文档是什么编码方式,输出编码均为UTF-8编码#但是像index 和 单纯的 find 方法会转成unicode编码方式再来操作,执行完后就要转码成utf8操作。#即先转码再转回来(先decode(‘utf8’)再encode(‘utf8’))

time.sleep(2)#每次完成一个任务就暂停2秒

#一般的字符串操作有rfind 从后前前找,beautifulsoup没有

#不可以用remove 方法,包括del pop这些方法只有list有#remove 是按照关键字删除,但是del 和pop 是按照索引删除

#表示去掉字串两头的空格,s.strip(rm)删除s字符串中开头、结尾处,位于rm序列里的字符,#当rm为空时,默认删除空白符(包括'\n', '\r', '\t', ' ')

#get_text() 方法可以拿到全部内容,而content数组拿到的是被内层标签分段内容块。transfercon=contentcut2.get_text()

s="原图"sx=s.decode('utf-8')#千万要注意不能把两句写在一起,动态编译不会识别的picurl=contentcut2.parent.next_sibling.find('a',text=sx)["href"]

#补充一点,双引号会对内容进行转义,单引号则不会

#为什么可以不用初始化对象就可以直接通过类名调用方法,当然是不可以的,运行的时候就会报错

#(这个错误很隐蔽,在编码过程中并不会报错,因为python是解释执行的#在运行过程中就会找不到这个方法。#解决方式,要么实例化对象后再调用方法,要么用“类方法”即在类名上加上@classmethod 修饰#并且要把方法的第一个默认参数写成cls)这里我采用第二种方法,在类名上加修饰符

#类方法,用classmethod来进行修饰

#类方法的隐含调用参数是类,而类实例方法的隐含调用参数是类的实例,静态方法没有隐含调用参数@classmethoddef findweibo(cls,sweb):

#注意:join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。#或者结合flag 和while 来判断 程程是否还有效 #is_alive(): Return whether the thread is alive.

##findAll 拿到的是一系列标签的list

resp1 = soup.find('input', attrs = {'name':'vk'})['value']

#中文正则表达式#前面带一个u 不是 r 并且 中文字符的编码范围是[\u4E00-\u9FA5]reg=u"<a href=('/[^\u4E00-\u9FA5]*?)[>]+?[\u4E00-\u9FA5]{2}</a>"

反正所有项目文件都在github 上/poiu1235/weibo-catch:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。