如何让tormysql进行插入?

时间:2018-05-07 00:30:05

标签: python mysql asynchronous web-scraping

我认为我对控制流程的理解是有缺陷的。我想要的是刮掉一堆URL,当我遇到它们时,从池中启动连接以将URL插入我的数据库。

我认为这里的问题是我对收益率的理解。如何使tormysql接受参数并异步使用连接将该参数写入数据库?

基本上,我只是希望insert_to_db()以异步方式将URL插入到我的数据库中。但是insert_to_db()实际上并没有运行。

from lxml import html
import tormysql
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException
import time
import sys
import csv
from shutil import copyfile

import requests
from bs4 import BeautifulSoup



pool = tormysql.ConnectionPool(
    max_connections = 20, #max open connections
    idle_seconds = 7200, #conntion idle timeout time, 0 is not timeout
    wait_connection_timeout = 3, #wait connection timeout
    host = "unidb.cfavdkskfrrc.us-west-2.rds.amazonaws.com",
    user = "#",
    passwd = "#",
    db = "diplomacy_data",
    charset = "utf8"
)

def insert_to_db(game_url):
    print(game_url)
    with (yield pool.Connection()) as conn:
        try:
            with conn.cursor() as cursor:
                yield cursor.execute("INSERT INTO FvA_urls(URL) VALUES('%s')" % game_url)
        except:
            yield conn.rollback()
        else:
            print('committed', game_url)
            yield conn.commit()


username = "#"
password = "#"
login_url = "https://webdiplomacy.net/logon.php"

driver = webdriver.Chrome()
driver.get(login_url)
driver.find_element_by_css_selector('body > div.content.content-follow-on > form > ul > li:nth-child(2) > input[type="text"]').send_keys(username)
driver.find_element_by_css_selector('body > div.content.content-follow-on > form > ul > li:nth-child(5) > input[type="password"]').send_keys(password)
driver.find_element_by_css_selector('body > div.content.content-follow-on > form > ul > li:nth-child(10) > input').click()

url = "https://webdiplomacy.net/gamelistings.php?"
params = "page-games=1&gamelistType=Finished&searchOn=on"
driver.get(url + params)
driver.find_element_by_css_selector('body > div:nth-child(5) > div:nth-child(2) > form > li:nth-child(5) > input[type="radio"]:nth-child(6)').click()
driver.find_element_by_css_selector('body > div:nth-child(5) > div:nth-child(2) > form > input').click()
# Get all the URLS
page_num = 0
while True:
    page_num += 1
    if page_num % 20 == 0:
        print(page_num)
    a = driver.find_elements(By.XPATH, '/html/body/div[5]/div[3]/div[*]/div[6]/div[2]/a')
    if len(a) < 1:
        pool.close()
        exit()
    else:
        for button in a:
            game_url = button.get_attribute('href')
            insert_to_db(game_url)
        driver.find_element_by_css_selector('body > div:nth-child(6) > div:nth-child(4) > div:nth-child(1) > div:nth-child(2) > a:nth-child(3) > img').click()

我可以在任何地方找到的TorMySQL用法的所有示例都只是对表的重复异步插入1。显然完全无用。

让每个连接独立完成某些事情是不可能的?就像这个库专门用于多次异步执行完全相同的事情一样吗?

1 个答案:

答案 0 :(得分:0)

我认为字符串插值的'%'语法是一种被证明易受SQL注入攻击的模式。必须正确转义包含在SQL文本中的任何可能不安全的值。

我还认为包含单引号会导致生成无效的SQL语法,并且语句的执行失败并出现语法错误

 cursor.execute("INSERT INTO FvA_urls(URL) VALUES('%s')" % game_url)
                                                  ^  ^   ^

(我可能正在咆哮错误的树。我没有通过测试验证这一点。也许单引号是必需的或可以容忍的,也许这个值正在被正确转义。)

我认为更好的模式是使用逗号代替百分号,并将元组作为参数传递,如下所示:

 cursor.execute("INSERT INTO FvA_urls(URL) VALUES( %s )", (game_url,))
                                                  ^  ^  ^ ^        ^^   

为了进行比较,请查看example/pool.py

中的这一行代码
    cur = yield POOL.execute("SELECT SLEEP(%s)", (t,))
                                               ^ ^ ^^

我打赌这就是问题所在。

但是在StackOverflow作为问答网站的精神中,我认识到这些问题也被提出来了:

问:是否不可能让每个连接独立完成某些事情?

问:就像这个库专门用于多次异步完成相同的事情一样吗?

example / pool.py中的代码是否回答了您的问题?正在使用不同的值执行相同的SQL语句,这正是您尝试完成的。