添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

本人菜鸡,有什么错误,还望大家批评指出,最近在更新python的爬虫系列,○( ^皿^)っHiahiahia…

该系列暂时总共有3篇文章,连接如下

【python】爬虫篇:python连接postgresql(一): https://blog.csdn.net/lsr40/article/details/83311860

【python】爬虫篇:python对于html页面的解析(二): https://blog.csdn.net/lsr40/article/details/83380938

【python】爬虫篇:python使用psycopg2批量插入数据(三): https://blog.csdn.net/lsr40/article/details/83537974

根据前两篇的思路,我们已经将html页面解析成功,接下来就是insert插入数据库,总所周知1W条数据一条一条插入,肯定是比一次性插入1W条来得慢的,所以最好要考虑到 批量插入数据库 ,既可以缓解数据库的压力,又能加快速度。

psycopg2的文档: http://initd.org/psycopg/docs/

# 插入数据库的方法
def insertManyRow(strings):
    # 这里就不需要遍历了,因为executemany接受
    # for index in range(len(rows)):
        conn_2 = psycopg2.connect(database="数据库", user="用户名", password="密码",
                                       host="ip",
                                       port="端口号")
        cur2 = conn_2.cursor()
        sql2 = "INSERT INTO test(字段1,字段2,字段3,字段4,字段5) VALUES(%s,%s,%s,%s,%s)"
        cur2.executemany(sql2, strings)
        conn_2.commit()
        conn_2.close()
    except Exception as e:
        print("执行sql时出错:%s" % (e))
        conn_word_2.rollback()
        conn_2.close()

关于这个strings可以传入什么样的参数类型?见如下代码:

# 第一种:strings可以是
strings = ({'num': 0, 'text': 'Zero'},
         {'num': 1, 'text': 'Item One'},
         {'num': 2, 'text': 'Item Two'},
         {'num': 3, 'text': 'Three'})
cur.executemany("INSERT INTO test VALUES (%(num)d, %(text)s)", rows)
# 第二种:strings可以是,我测试的时候是第二种速度更快,但是应该没有快多少
strings = [[0,'zero'],[1,'item one'],[3,'item two']]
sql2 = "INSERT INTO test(num,text) VALUES(%s,%s)"
cur.executemany(sql,strings)

理论上来说,插入就批量插入就好了,不要搞什么多线程,但是如果是多线程获取数据的话,看起来也只能每个线程各自往数据库中插入 (下一篇文章会使用其他技术来解决这个问题) ,但是请注意数据库连接有限,在使用的时候注意看下数据库连接被占了多少,是否有释放连接!

因此来总结下这整套方案用的东西和缺点:

1、先从数据库查出数据

2、将每条数据通过urllib和python多线程的方式请求到页面

3、通过bs4或者xpath或者其他的html页面解析的方式去解析到我想要的东西

4、将我想要的东西一批一批的传入批量插入数据库的代码中,然后执行批量插入

每个点会遇到的问题:

1、从数据库,我一次性查出200W条数据,python报了个 内存溢出 的错误,我一直不太清楚python的内存机制,其实java我也没有非常清晰,希望以后会有机会多学学! 可以写个循环,(在sql里面做排序,然后limit偏移量叠加)就像做java的分页功能一样,每次处理一页的数据,处理完再从数据库查询下一页(这种方式在 该系列的第一篇文章中有提到,用offset和limit实现 )。当然我认真搜索了下,发现了 executemany方法, 也就是说,我可以查询全部数据,但是并不用一次性全部加载出来,分批加载就可以(这里我没实际测试过会不会内存溢出,但是我想应该是不会溢出,毕竟不是一次性将全部数据取出),每次调用executemany,返回的结果相当于有一个游标往下偏移,就是不会查出重复数据,这样也是能够满足我的需求的。

executemany 的API: http://initd.org/psycopg/docs/cursor.html?highlight=fetchmany#cursor.fetchmany

代码如下:

if __name__ == '__main__':
    conn = psycopg2.connect(database="数据库", user="用户名", password="密码",
                                   host="ip",
                                   port="端口")
    cur = conn.cursor()
    # 查询条件
    sql = "查询全量数据的sql"
    cur.execute(sql)
    # 手动给定循环次数5次
    for i in range(5):
        # 每次查询1000条数据
        rows = cur.fetchmany(size=1000)
        print('第{i}次拉取到数据'.format(i=i+1))
        for row in rows:
            print(row)
    conn.close()

2、这步就考虑用多线程还是多进程,每个线程(进程)的数据从哪来,必须不能重复;有时候在请求页面的时候会 假死(卡住) ,相应的api是否有timeout时间,例如我用的 urllib. request.urlopen(url,timeout=5) 就有这样的参数;还有一点,是否会被 封号 ,多久解封,我在做的这个是,今天被封,得等到明天才能再用,所以得有多个ip或者伪装自己的方式,并且要做爬取该文章的时候是否已经被封了,如果被封了可以发警报或者停止继续爬等等,避免浪费资源。

3、解析的方式很多,在能接受消耗资源的情况下,哪种更快?是否有更好的方式来获取 (该系列第二篇文章有介绍) ?解析出来的数据如何拼接,传递到下一个方法 我会在下一篇文章来谈谈这个点 是这个阶段要考虑的问题。

4、批量插入数据库,该篇文章提供了一种方法,就是解析完之后把数据List加到一个外层的List列表中(List嵌套,类似如上代码strings的第二种方式),传入批量插入的代码中执行 executemany ,然后我看到除了 executemany 之外还有一个 execute_batch ,并且可以设置 page_size (默认值是100),这是一次能插入100条数据,然后插入多个批次固定条数的sql,我自己没有测试过,因为我每个批次数据量不大,但是看stackoverflow上,有这么一段话。

大概的意思就是说在他的测试中execute_batch的性能是executemany的两倍,并且可以调整每次插入的数据条数(page_size)。

链接在这里: https://stackoverflow.com/questions/2271787/psycopg2-postgresql-python-fastest-way-to-bulk-insert

总结:到此,结构如下

然鹅我还是想要插入数据库线程只有一条。。。。也就是多个线程是否能够把数据放入一个统一的地方,然后单独启动一条线程,把这个地方的数据批量插入数据库?

欲知后事如何,且听下回分解!

好了标准结尾,菜鸡一只,如果有更好的思路或者不明白的问题可以给我评论,但求轻喷~

本人菜鸡,有什么错误,还望大家批评指出,最近在更新python的爬虫系列,○( ^皿^)っHiahiahia…该系列暂时总共有3篇文章,连接如下【python】爬虫篇:python连接postgresql(一):https://blog.csdn.net/lsr40/article/details/83311860【python】爬虫篇:python对于html页面的解析(二):htt...
一种是导入sqlalchemy包,另一种是导入 psycopg2 包。具体用法如下(此处以postgre 数据 库举例)第一种:# 导入包 from sqlalchemy import create_engine import pandas as pd from string import Template engine = create_engine("oracle://user:pwd@***:***...
目录前言一、 使用 pycharm连接postgresSQL1-1、连接 数据 库1-2、关闭 数据 库1-3、cursor类1-4、 使用 python 的configparser包来解析配置文件 psycopg2 库是 python 用来操作postgreSQL 数据 库的第 方库。 一、 使用 pycharm连接postgresSQL 1-1、连接 数据 库 try : conn = psycopg2 .connect(database='postgres', user='postgres', password='xuha
之前写过 python 连接postgresql的方法,今天在网上详细总结了一下 psycopg2 使用 方法 使用 *.ini文件( python 的configparser包可以解析这种类型的配置文件)保存 数据 库连接的配置信息。 使用 psycopg2 .connect函数获得connection对象。 使用 connection对象创建cursor对象。 使用 cursor对象执行sql语句提交或者回滚transaction。 使用 cursor对象fetchone获得查询结果。 关闭cursor对象和connec
import psycopg2 conn = psycopg2 .connect(host=***, port=***, database=***, user=***, password=***) cur = conn.cursor() cur. execute ("select to_regclass(" + "\'" + ta...
psycopg2 数据 批量插入 问题记录 由于最近用到greenplum,需要进行一些 数据 批量插入 操作,由于其操作方式与postgresql相同,因此采用的是 psycopg2 (2.8.4) 做底层驱动。 由于 数据 量较大,所以采用了 批量插入 操作,也就是其自带的 execute many,从名字来看会给我们其真的是 批量插入 的错觉(搜了下,大部分搜索结果也是说 批量插入 使用 该操作,坑~(⊙﹏⊙)),但是,实际...
import psycopg2 ## 连接到一个给定的 数据 库 conn = psycopg2 .connect(database="db", user="wjz",password="XXX", host="101.XX.X.X", port="5432") ## 建立游标,用来.
导入与创建连接 import psycopg2 conn = psycopg2 .connect(database='dbschool', user='postgres', password='admin', host='127.0.0.1', port='5432') cur = conn.cursor() connection connection提供了常用的 数据 库操作:
好的,这是一个很常见的问题。 Python 爬虫 获取到 数据 后,可以将 数据 写入到 数据 库中。一般来说,我们可以 使用 Python 中的第 方库来实现 数据 库的连接和操作,比如`pymysql`、`sqlite3`、` psycopg2 `等。 以下是一个 使用 `pymysql`库将 数据 写入MySQL 数据 库的示例代码: ``` python import pymysql # 连接 数据 库 conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='test') # 获取游标 cursor = conn.cursor() # 插入 数据 sql = "INSERT INTO user(name, age) VALUES (%s, %s)" cursor. execute (sql, ('Tom', 20)) conn.commit() except Exception as e: print(e) conn.rollback() # 关闭连接 cursor.close() conn.close() 这段代码中,我们先 使用 `pymysql`库的`connect`函数连接 数据 库,然后 使用 `cursor`方法获取游标进行 数据 操作。接着,我们通过` execute `方法执行插入 数据 的SQL语句,并用`commit`方法提交事务。如果插入 数据 的过程中出现异常,我们 使用 `rollback`方法回滚事务,最后关闭游标和 数据 库连接。 当然,具体的 数据 库连接和操作方法因不同的 数据 库而异,但大体相似。