Python BeautifulSoup 城市刮削并发症

Python BeautifulSoup City Scraping Complications

我正试图从 craigslist 中删除国家和城市,我非常接近。

我遇到的问题是城市会跳过并转到下一个框。

我想要实现的输出是:

COUNTRY   |    STATE   |   CITY
US:          ALABAMA:       AUBURN
US:          ALABAMA:       BIRMINGHAM
US:          ALABAMA:       DOTHAN

但我得到的是:

COUNTRY   |    STATE   |   CITY
US:          ALABAMA:       AUBURN
US:          ALABAMA:       ANCHORAGE / MAT-SU
US:          ALABAMA:       FLAGSTAFF / SEDONA

然后当我到达列的末尾时,STATE 变为下一个 STATE。

这是我当前的代码:

from BeautifulSoup import BeautifulSoup
import urllib2


soup = BeautifulSoup(urllib2.urlopen("http://www.craigslist.org/about/sites").read())
soup.prettify()

for h1 in soup.findAll('h1'):
    colmask_div = h1.findNextSibling('div')

    for box_div in colmask_div.findAll('div'):
        h4 = box_div.find('h4')

        for ul in box_div.findAll('ul'):
            print'{} : {} : {}'.format(h1.text, h4.text, ul.li.a.text)
            raw_input()

在某处跳过框但找不到位置!谢谢。这不是家庭作业,只是个人学习项目beautifulsoup :)

您的代码存在问题,您是:

  1. 获取列中的第一个 h4 元素(州名称)
  2. 获取整个列中的所有 ul 个元素(城镇列表)
  3. 对于每个城镇列表,仅输出第一个 li 元素(城镇名称)
  4. 进入下一个城镇列表,而不进入下一个州

我会选择更像这样的东西:

for country in soup.findAll('h1'):
    country_data = country.findNextSibling('div')
    for state, towns in zip(country_data.findAll('h4'), country_data.findAll('ul')):
        for town in towns.findAll('li'):
            print '{} : {} : {}'.format(country.text, state.text, town.text)
            raw_input()

您不需要依次处理每一列。在这里,我让 BS 完成将一个国家的顶级 div 中的所有嵌套 h4ul 元素作为两个列表获取的工作。

然后我使用 python zip() 函数逐步迭代这两个列表。


输出

US : Alabama : auburn
US : Alabama : birmingham
US : Alabama : dothan
...
US : Alabama : tuscaloosa
US : Alaska : anchorage / mat-su
...
US : Territories : U.S. virgin islands
Canada : Alberta : calgary
...

性能

在 Python 2 中,您可以使用 itertools.izip() 提高此代码的性能。这不会从两个输入在内存中创建整个元素对列表,而是使用生成器。

在 Python 3 中,常规 zip() 函数默认执行此操作。