【问题标题】:Problems scraping URLs and nested CSV to combine with python抓取 URL 和嵌套 CSV 以与 python 结合时出现问题
【发布时间】:2017-05-05 23:46:20
【问题描述】:

我的项目要求我分几个步骤从网站上抓取信息,每一步都添加新的页面和变量以在后续步骤中抓取。我正在为此使用 Python……仅在 3 个月前学习了非常基本的方面,仍然很新。

抓取顺序如下:

步骤 0: 要抓取的顶级 URL 的 CSV1 文件(url_1),总共大约 20 个 URL

-->

第 1 步: 获取 scrape1.py,它使用 Selenium Firefox Webdriver 加载 CSV1 中的每个 (url_1) 链接,以使 CSV2 在列中包含以下中间类别变量:(variable1)、(variable2)、(variable3)、(variable4)、(variable5 ), (url_2)...每次加载 (url_1) 都会产生 12-24 行带有唯一 (url_2) 链接的新行,因此总共大约 400+ 行

-->

第 2 步: 使用 scrape2.py 和 Beautiful Soup 在 CSV2 中加载每个 (url_2) 链接,并使 CSV3 在列中包含以下最终类别变量:(variable_A)、(variable_a)、(url_a)、(variable_B)、(variable_b)、( url_B), (url_b)。每个 (url_2) 链接产生 20+ 每个变量 (A, a, B, b) 和 url (a, B, b),因此输出将超过 10,000 行(目前仅在较小版本的 CSV2 上运行只有 5 行 url_2)

-->

第三步:

将所有变量合并到一个 CSV4 文件中。

我遇到的问题在第 3 步。我能够创建 CSV1、CSV2 和(截断的)CSV3。我能够制作 scrape1.py 和 scrape2.py 并成功收集变量和 URL。但我无法弄清楚如何将所有变量放入一个 CSV 文件中。尤其是因为每个阶段都会以指数方式增加后续变量的数量,因此 CSV1 中的一行 (url_1) 将在 CSV3 中产生 200-400+ 行变量。我需要将变量从一个 CSV 文件“结转”到下一个文件,但是对于每个新的行迭代,新文件必须在其中多次包含结转变量,而不仅仅是一次,所以只需将它们添加为新列将不起作用。

最终输出应该是:

CSV1: (url_1) [x20]

CSV2:对于每个 (url_1),大约 22 行: (variable1), (variable2), (variable3), (variable4), (variable5), (url_2)

CSV3:对于每个 (url_2),大约 30 行: (variable_A), (variable_a), (url_a), (variable_B), (variable_b), (url_B), (url_b)

CSV4:CSV3 中的每一行都与以前的变量一起复制,这样每一行都有: (url_1), (variable1), (variable2), (variable3), (variable4), (variable5), (url_2),(variable_A), (variable_a), (url_a), (variable_B), (variable_b), (url_B ), (url_b)

有人建议我尝试 Pandas,但我无法弄清楚如何仅使用我阅读的其他项目的内容来实现它。

任何帮助将不胜感激!

【问题讨论】:

  • 欢迎来到 Stack Overflow!您可以先take the tour 学习How to Ask a good question 并创建Minimal, Complete, and Verifiable 示例。这让我们更容易为您提供帮助。
  • @StephenRauch 感谢您的回复...我在发布之前确实阅读了这两个资源,并尝试按照这些准则来制作我的问题。您的评论表明我的工作没有我希望的那么好,所以我编辑以(希望)增加一些清晰度。
  • 这里有几个我最近回答的问题,这些问题显示了这里的人们希望看到的让问题更容易回答的问题。 stackoverflow.com/questions/43810094/… & stackoverflow.com/questions/43765796/…。而在构建 MCVE 时,关注的结构并没有那么大。尽管描述大小很重要。但是你最好的结果将来自非常具体和可重复的 MCVE。

标签: python csv pandas selenium beautifulsoup


【解决方案1】:

使用带有列的 CSV:

  • CSV1
    • url_1
  • CSV2
    • url_1
    • 变量1
    • url_2
  • CSV3
    • url_2
    • 变量_A

如果您想合并这些 CSV,只需使用 pandas.merge

pandas.merge(CSV1, CSV2) 将使用 CSV1 和 CSV2 的公共列(在示例中为 url_1 列)连接它们。

看例子here

【讨论】:

  • 感谢您的回复!棘手的部分是它不是一个合并。每个 CSV 列表每次都会生成一个更大的列表,我希望一些变量可以延续。我设法使用不同的技术做到了这一点,但你发给我的帮助解决了这个问题!
【解决方案2】:

我终于设法解决了这个问题。感谢其他用户的帮助。解决方案不是合并 CSV,而是将一些变量转移到新的变量中。我想我会发布解决方案,以防其他人以后发现它有用。

CSV1,每个变量在单独的行中:

    url_1_00.html
    url_1_01.html
    url_1_02.html

(完整的 CSV1 包含约 50 个 URL)

每个 URL 都指向一个页面,其中包含(复杂的)所需信息列表,该列表长 10-30 项,其中一项是第二个 URL。我需要将每个列表中的每个项目,从 50 个 URL 中的每一个中抓取到一个新的 CSV 中。

Scrape1.py:(注意:我已将这段代码设为通用代码;实际上,刮板变量需要更多导航和一些点击和下拉菜单,这就是我特别使用 Selenium 的原因)。

    ### HEADER: IMPORTS AND DEFINITIONS ###

    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys 
    from selenium.webdriver.support.ui import Select
    import datetime
    import time
    import csv

    driver=webdriver.Firefox()

    raw_data_file = open("CSV1.csv", 'rU')
    csv_data_file = csv.reader(raw_data_file, delimiter=',', quotechar='"')
    csv_data_file.next()

    ###DEFINE FUNCTIONS HERE###

    def scraper():
            var_1 = driver.find_element_by_id('var_1_id').text
            var_2 = driver.find_element_by_css_selector('.list_item.odd')
            lotta_varslist = driver.find_element_by_css_selector('.list_item.odd')
            for each in lotta_varslist:
                    var_3 = each.find_element_by_class_name('classwhut')
                    var_4 = each.find_element_by_tag_name('strong')
                    var_5 = each.find_element_by_id('id_whut')
                    url_2 = each.find_element_by_tag_name('a').get_attribute("href")
                    summary=[url_1, var_1, var_2, var_3, var_4, var_5, url_2]
                    #NOTICE url_1 is in this summary even though it's origin is 
                    #in CSV1, not scraped from the page like all the other 
                    #variables defined in this function...it can carry over
                    scrapetehvars.append(summary)

    def write_to_csv():
            with open('CSV2.csv', 'wb') as outfile:
            writer = csv.writer(outfile)
            writer.writerow(["url_1", "var_1", "var_2", "var_3", "var_4", "var_5", "url_2"]) 
            #NOTICE url_1 is here as well ^^^
            writer.writerows(scrapetehvars)

    ###BEGIN ACTUAL PROGRAM###

    scrapetehvars=[]

    for each in csv_data_file:
            url_1=each[0] 
            #NOTICE this is where url_1 is actually 
            #defined, pulled from CSV1 using the 
            #csv_data_file variable defined in the Header
            driver.get(url_1)
            scraper()
            write_to_csv()
            time.sleep(1)

    print "ALL DONE!"

    driver.close()
    driver.quit()

这里有几点注意事项: CSV1 包含所有初始 URL,定义为 url_1。

这产生了 CSV2,其中包含我需要在其中抓取的下一组 URL。 CSV2 有 800+ 行长(所以大约 50 个 url_1 的 URL 产生了 800+ 个 url_2 的 URL)

CSV2 示例,每组变量位于不同的行中,变量以逗号分隔:

    url_1_00, var_1_00, var_2_00, var_3_00, var_4_00, var_5_00, url_2_00.html  
    url_1_00, var_1_01, var_2_01, var_3_01, var_4_01, var_5_01, url_2_01.html  
    url_1_00, var_1_02, var_2_02, var_3_02, var_4_02, var_5_02, url_2_02.html  
    url_1_00, var_1_03, var_2_03, var_3_03, var_4_03, var_5_03, url_2_03.html  
    url_1_00, var_1_04, var_2_04, var_3_04, var_4_04, var_5_04, url_2_04.html

(完整的 CSV2 包含约 800 行上述变量 url 集)

现在我需要抓取每个 url_2 和另一个(复杂的)变量列表。 url_2 页面上的每个列表包含 30-100 个具有 ~4 个变量属性的项目,我需要将每个项目刮到自己的行并添加其变量属性,同时保留上一次刮取的信息(url_1、var_1、var_2 ...通过 url_2)。

结果如下:

Scrape2.py:(注意:我已将这段代码设为通用;这部分不需要点击,所以我使用了 BeautifulSoup)。

    ### HEADER: IMPORTS AND DEFINITIONS ###

    import requests
    from bs4 import BeautifulSoup
    import time 
    import csv, codecs, cStringIO

    raw_data_file = open("CSV2.csv", 'rU')
    csv_data_file = csv.reader(raw_data_file, delimiter=',', quotechar='"')
    csv_data_file.next()

    ###DEFINE FUNCTIONS HERE###

    def scrapertron():
            moarvarslist=soup.find_all('tr')
            for each in moarvarslist:
                    var_a = None
                    try: 
                            var_a = each.find('td', class_="classwhut")
                    except: pass
                    url_a = None
                    try: 
                            url_a = each.find('a').get('href')
                    except: pass
                    var_b = None
                    try: 
                            var_b = each.find('tr', class_="heyyyanotherone")
                    except: pass
                    url_b = None
                    try: 
                            url_b = each.find('a').get('href')
                    except: pass
                    newsummary=[url_1, var_1, var_2, var_3, var_4, var_5, url_2, var_a, url_a, var_b, var_b]
                    # NOTICE as in the previous scrape, this carries over
                    # variables that aren't in the scrape from CSV2, namely
                    # url_1, var_1, var_2, var_3, var_4, var_5, and url_2
                    scrapeallvars.append(summary)

    def write_to_csv():
            with open('CSV3.csv', 'wb') as outfile:
            writer = csv.writer(outfile)
            writer.writerow(["url_1", "var_1", "var_2", "var_3", "var_4", "var_5", "url_2", "var_a", "url_a", "var_b", "var_b"])
            # NOTICE again, the carry over variables from CSV2 here ^^^
            writer.writerows(scrapeallvars)

    ###BEGIN ACTUAL PROGRAM###

    scrapeallvars=[]

    for each in csv_data_file:
            url_1=each[0]
            var_1=each[1]
            var_2=each[2]
            var_3=each[3]
            var_4=each[4]
            var_5=each[5]
            url_2=each[6]
            # The variables from CSV2 are actually defined here, after
            # they are pulled using csv_data_file

            response = requests.get(url_2)  
            soup = BeautifulSoup(response.content, "lxml")

            scrapertron()
            write_to_csv()
            time.sleep(3)

    print "ALL DONE!"

这会在最终文件 CSV3 中生成所有需要的变量。不再需要 CSV4。所有 url_2 URL 在列表中产生 30-100 个新变量项,这导致最终文件中有 120,000+ 行。这种抓取需要更长的时间,因为它遍历了 800 多行 url_2。对我来说,这花了大约一个小时,但如果我没有使用 time.sleep() 可能需要 15-20 分钟,但我不想压倒我正在抓取的网站。

CSV3 输出示例,每组变量位于不同的行中,变量以逗号分隔:

    url_1_00, var_1_00, var_2_00, var_3_00, var_4_00, var_5_00, url_2_00, var_a_000, url_a_000, var_b_000, url_b_000  
    url_1_00, var_1_00, var_2_00, var_3_00, var_4_00, var_5_00, url_2_00, var_a_001, url_a_001, var_b_001, url_b_001  
    url_1_00, var_1_00, var_2_00, var_3_00, var_4_00, var_5_00, url_2_00, var_a_002, url_a_002, var_b_002, url_b_002  
    url_1_00, var_1_00, var_2_00, var_3_00, var_4_00, var_5_00, url_2_00, var_a_003, url_a_003, var_b_003, url_b_003

知道这很长,但也许某个地方的某个人有时需要它!

【讨论】:

    猜你喜欢
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 2022-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多