在循环浏览网页时编写CSV文件

时间:2015-03-04 18:43:54

标签: python loops csv

这是我之前关于循环浏览多个网页的问题的后续问题。我是编程新手...所以我感谢你的耐心和非常明确的解释!

我已经通过许多网页编写了一个循环。在每个页面上,我想抓取数据,将其保存到变量或csv文件(更容易/更稳定),然后单击" next"按钮,在第二页上刮取数据并将其附加到变量或csv文件等。

具体来说,我的代码如下所示:

url="http://www.url.com"
driver = webdriver.Firefox()
driver.get(url)
(driver.page_source).encode('utf-8')
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html)

wait = WebDriverWait(driver, 10)

while True:
    # some code to grab the data
    job_tag={'class': re.compile("job_title")}
    all_jobs=soup.findAll(attrs=job_tag)
    jobs=[]
    for text in (all_jobs):
     t=str(''.join(text.findAll(text=True)).strip()) 
     jobs.append(t)

    writer=csv.writer(open('test.csv','a', newline=''))
    writer.writerows(jobs)

    # click next link
   try:
       element=wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='reviews']/a/span[starts-with(.,'Next')]")))
       element.click()
   except TimeoutException:
        break 

它运行没有错误,但是 1)文件一遍又一遍地收集第一页的数据,但不收集后续页面的数据,即使循环正确执行(最终,我并不介意重复的条目,但我确实需要来自所有页面的数据) )。 我怀疑我需要重新定义"每个新页面的汤,我正在研究如何使bs4访问这些网址。

2)最后一页没有" next"按钮,因此代码不会附加最后一页的数据(当我在csv行中使用'而不是' a'时,我会收到该错误的数据写入csv文件的倒数第二页。

此外,尽管这是一个小问题,但数据在csv中每个单元格写入一个字母,即使我在Python中使用bs4运行该部分时,数据也已正确格式化。我错过了什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

  

我怀疑我需要重新定义"每个新页面的汤

确实,你应该。您看,您的while循环与soup一起运行时始终引用您在进入while循环之前所做的相同旧对象。您应该将soup重新绑定到新的BeautifulSoup实例,该实例很可能是您在anchor(代码a)后面找到的网址最后一行:

element=wait.until(EC.element_to_be_clickable((By.XPATH, "//*[@id='reviews']/a/span[starts-with(.,'Next')]")))

您可以仅使用soup访问它(请注意,我没有对此进行测试以确保正确性:没有页面的实际来源,我猜测):

next_link = soup.find(id='reviews').a.get('href')

然后,在while循环结束时,您将重新绑定soup

soup = BeautifulSoup(urllib.request.urlopen(next_link.read()))

你仍然应该添加一个try - except子句来捕获它在最后一页上找不到的错误,当它找不到最后一个"下一个"链接,然后突破循环。

请注意,selenium很可能不是您的用例所必需的,bs4就足够了(但要么会有效)。

  

此外,尽管这是一个小问题,但数据在csv中每个单元格写入一个字母,即使我在Python中使用bs4运行该部分时,数据也已正确格式化。我错过了什么?

您创建的writer实例期望其writerows方法具有可迭代性。你传给它一个字符串(其中可能包含kommas,但那不是csv.writer所看到的:它会在每两个项目之间添加kommas(或者你在其构造中指定的任何分隔符)可迭代的)。 Python字符串是可迭代的(每个字符),因此writer.writerows("some_string")不会导致错误。但你很可能想要这个:

for text in (all_jobs):
    t = [x.strip() for x in text.find_all(text=True)]
    jobs.append(t)

作为评论的后续行动: 您希望根据新网址更新soup,您可以从1, 2, 3 Next >>div容器中检索到具有特定{{1}的新网址只有id才能轻松提取。下面的代码是一个相当基本的例子,展示了如何完成。提取相关的内容是由您自己的抓取代码完成的,您必须按照示例中的说明添加这些代码。

BeautifulSoup