本文知识点:
1、复习了类的写法。
2、复习了scrapy先大范围取数,然后for循环取每一个item的用法。取大范围值的时候,在python中print不出来也没有问题,比如本文中的node_list,for循化中可以取出就可以了。
3、学习了写入Mysql时自动生成时间的方法。
4、学习了xpaht中的“.//”、“./”的写法。
5. Mysql避免数据重复插入的方法。
一、正则
折腾了一个早上,发现原来是目标网页的问题:http://rank.chinaz.com/?host=zz.xhj.com&st=0&c=&sortType=0&page=1
网页上的整体指数、PC指数、移动指数各栏数据在网页源码是有差异的,导致有的数据可以通过正则取到,有的取不到!
取的结果是这样的:
二、别人推荐的讲python类的视频
三、代码
后来放了几天,学习了一点正则,复习了一下scrapy,最后终于搞定了:
11 |
"" "一个采集chinaz关键词指数的类" "" |
12 |
def __init__(self, url): |
13 |
# init进行初始化参数,把我们需要从外部传入的参数,作为类的属性 |
15 |
self.conn=MySQLdb.connect(host= "localhost" ,user= "root" ,passwd= '' ,db= "testpy" ,port=3306,charset= "utf8" ) #连接数据库 |
16 |
self.cursor=self.conn.cursor() #定位一个指针 |
18 |
def get_url_content(self,url, max_try_number=5): |
23 |
return requests.get(url, timeout=5) |
24 |
except Exception as http_err: |
25 |
print (url, "抓取报错" , http_err) |
27 |
if try_num >= max_try_number: |
28 |
print ( "尝试失败次数过多,放弃尝试" ) |
32 |
def get_total_page(self,content): |
34 |
selector = etree.HTML(content.text) |
35 |
total_page_num = selector.xpath( "//span[@class='col-gray02']/text()" ) # 获取总页数 |
36 |
total_page_num=re.sub(r '\D' , '' ,total_page_num[0]) |
37 |
return int(total_page_num) |
39 |
def insert_to_db(self,word,total_index,pc_index,m_index): |
41 |
dt=datetime.datetime.now(). strftime ( "%Y-%m-%d %H:%M:%S" ) |
42 |
#insert ignore into 是避免重复插入 |
43 |
insert_result = self.cursor.execute( "insert ignore into keywords(word,total_index,pc_index,m_index,create_time) VALUES ('%s',%s,%s,%s,str_to_date(\'%s\','%%Y-%%m-%%d %%H:%%i:%%s'))" %(word,total_index,pc_index,m_index,dt)) |
44 |
print ( "insert {}" .format(insert_result)) |
45 |
print ( '[关键词:' ,word, '-----------已成功添加到数据库---------------' ) |
49 |
def get_keywords(self,i): |
52 |
content=requests.get(url).text |
53 |
selector = etree.HTML(content) |
54 |
node_list = selector.xpath( "//li[@class='ReListCent ReLists clearfix']" ) |
55 |
for node in node_list: |
56 |
keywords = node.xpath( "./div[@class='w25-0 tl pl10 pr pbimg showt']/a/text()" )[0] |
57 |
index_list = node.xpath( "./div[@class='w8-0']/a/text()" ) |
58 |
if len(index_list) ==0: |
59 |
index_total = node.xpath( ".//span[@title='整体搜索量']/a/text()" )[0] |
60 |
index_pc = node.xpath( ".//span[@title='PC搜索量']/a/text()" )[0] |
61 |
index_m = node.xpath( ".//span[@title='移动搜索量']/a/text()" )[0] |
63 |
index_total = index_list[0] |
64 |
index_pc = index_list[1] |
65 |
index_m = index_list[2] |
66 |
print ( '采集关键词:' ,keywords, ',整体指数:' ,index_total, ',PC指数:' ,index_pc, ',移动指数:' ,index_m) |
67 |
self.insert_to_db(keywords,index_total,index_pc,index_m) |
68 |
print ( "已经完成第{}页数据的抓取" .format(i)) |
75 |
def get_all_content(self): |
77 |
r = self.get_url_content(url) |
78 |
total_page_num = self.get_total_page(r) #这里调用函数self一定不能少 |
79 |
print ( "关键词总页数为{}页" .format(total_page_num)) |
80 |
if total_page_num <= 9: |
81 |
for i in range(1,total_page_num+1): |
89 |
A = KeywordsTool( "sohu.com" ) |
四、关于Mysql版本的问题
想实现在mysql中插入数据的时候在create_time字段自动加入时间,可是搞了半天没搞出来,后来才发现原来是Mysql版本的问题,我的mysql版本太低了。找不到这个current_timestamp的选项。
但是将时间插入mysql也老是出错,后来终于搞定了,应该用下面的代码
1 |
dt=datetime.datetime.now(). strftime ( "%Y-%m-%d %H:%M:%S" ) |
2 |
sql = "INSERT INTO tb_emotion (name,datetime,emotion) VALUES ('%s',str_to_date(\'%s\','%%Y-%%m-%%d %%H:%%i:%%s'),'%s')" % (name,dt,emotion) |
四、设置唯一索引
这个要在Navicat里面设置,在Mysql中没有找到设置的地方。
参考:https://www.jianshu.com/p/12b167812fdb
五、Mysql避免重复插入数据的方法
1 |
insert ignore into table_name(email,phone,user_id) values( '[email protected]' , '99999' , '9999' ), |
如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用。这样当有重复记录就会忽略,执行后返回数字0,如果插入成功,则返回数字1。如下图所示,后面的两次不执行。
参考:https://blog.csdn.net/qq_35044419/article/details/81974207