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 :)
您的代码存在问题,您是:
- 获取列中的第一个
h4
元素(州名称)
- 获取整个列中的所有
ul
个元素(城镇列表)
- 对于每个城镇列表,仅输出第一个
li
元素(城镇名称)
- 进入下一个城镇列表,而不进入下一个州
我会选择更像这样的东西:
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
中的所有嵌套 h4
和 ul
元素作为两个列表获取的工作。
然后我使用 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()
函数默认执行此操作。
我正试图从 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 :)
您的代码存在问题,您是:
- 获取列中的第一个
h4
元素(州名称) - 获取整个列中的所有
ul
个元素(城镇列表) - 对于每个城镇列表,仅输出第一个
li
元素(城镇名称) - 进入下一个城镇列表,而不进入下一个州
我会选择更像这样的东西:
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
中的所有嵌套 h4
和 ul
元素作为两个列表获取的工作。
然后我使用 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()
函数默认执行此操作。