Python BeautifulSoup 网络抓取:获取没有链接或 class 标签的文本
Python BeautifulSoup webcrawling: Getting text that doesn't have links or class tags
我要抓取的站点是 http://www.boxofficemojo.com/yearly/chart/?yr=2015&p=.htm。
该站点有一个电影列表,对于每部电影,我想在 table 中获取以下信息,不包括日期。
我遇到了麻烦,因为文本没有链接或任何 class 标签。我已经尝试使用多种方法,但其中 none 有效。
这是我目前使用的一种方法,只是为了获取每部电影的排名。
我希望输出只是一个由每部电影的排名组成的列表列表,然后是另一个包含每部电影列表、周末总收入等的列表。
listOfRanks = [[1, 1, 1,], [1, 2, 3], [3, 5,1]], etc.
listOfWeekendGross = [[208,806,270,106588440,54200000], [111111111, 222222222, 333333333]]
def getRank(item_url):
href = item_url[:37]+"page=weekend&" + item_url[37:]
response = requests.get(href)
soup = BeautifulSoup(response.content, "lxml") # or BeautifulSoup(response.content, "html5lib")
rank = soup.select('tbody > tr > td > center > table > tbody > tr > td > font')
print rank
这是我调用此函数的地方 -
def spider(max_pages):
url = 'http://www.boxofficemojo.com/yearly/chart/?page=' + str(max_pages) + '&view=releasedate&view2=domestic&yr=2015&p=.htm'
source_code = requests.get(url)
plain_text = source_code.text
soup = BeautifulSoup(plain_text)
for link in soup.select('td > b > font > a[href^=/movies/?]'):
href = 'http://www.boxofficemojo.com' + link.get('href')
getRank(href)
问题是 getRank(href) 方法没有正确地将排名添加到列表中。我认为问题在于这条线 -
rank = soup.select('tbody > tr > td > center > table > tbody > tr > td > font')
这可能不是获取此文本的正确方法。
我怎样才能从该站点获得所有排名、周末总收入等?
++++++++++++++++++++++++++++++++++
是的,问题出在您使用的选择器上。你看,该网站中的标记 非常糟糕 。 table 编码不正确,它们实际上缺少 tbody
标签,但是 Google Chrome 还是添加了它们,这就是为什么您会在 Web 开发人员工具中看到它们.
但是,正如我所说,它们不在实际的 HTML 代码中,因此如果您在你的选择器。看起来 table 有 class chart-wide
,因此您可以使用以下目标行:
rows = soup.select('.chart-wide tr')
之后,您可以迭代那些 rows
,跳过第一个(因为那是 header)并解析其他的和它们各自的单元格。
像这样:
def getRank(item_url):
href = item_url[:37]+"page=weekend&" + item_url[37:]
response = requests.get(href)
print response.status_code, "for", href
soup = BeautifulSoup(response.content) # or BeautifulSoup(response.content, "html5lib")
rows = soup.select('.chart-wide tr')
header_skipped = False
for row in rows:
if not header_skipped:
header_skipped = True
continue
headers = "Date Rank WeekendGross Change Theaters Change/Avg GrossToDate Week".split()
for header, child in zip(headers, row.children):
print header, ":", child.text
貌似这张图table是动态生成的,使用Phantomjs,一切正常
from selenium import webdriver
from bs4 import BeautifulSoup
driver = webdriver.PhantomJS()
driver.get('http://www.boxofficemojo.com/movies/?page=weekend&id=jurassicpark4.htm')
soup = BeautifulSoup(driver.page_source)
soup.select('table.chart-wide tbody tr td font')
出[1]
[<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=date&order=DESC&p=.htm"><b>Date<br>(click to view chart)</br></b></a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=rank&order=ASC&p=.htm">Rank</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=wkndgross&order=DESC&p=.htm">Weekend<br>Gross</br></a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=perchange&order=DESC&p=.htm">%<br>Change</br></a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=theaters&order=DESC&p=.htm">Theaters</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=theaterchange&order=ASC&p=.htm">Change</a> / </font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=avg&order=DESC&p=.htm">Avg.</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=todategross&order=DESC&p=.htm">Gross-to-Date</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=weeknum&order=ASC&p=.htm">Week<br>#</br></a></font>,
<font size="2"><a href="/weekend/chart/?yr=2015&wknd=24&p=.htm"><b>Jun 12–14</b></a></font>,
<font size="2">1</font>,
<font size="2">8,806,270</font>,
<font size="2">-</font>,
<font size="2">4,274</font>,
.
.
.
<font size="2">0,373,420</font>,
<font size="2">3</font>,
<font size="2"><a href="/weekend/chart/?yr=2015&wknd=27&p=.htm"><b>Jul 3–5</b></a></font>,
<font size="2">2</font>,
<font size="2">,242,025</font>,
<font size="2"><font color="#ff0000">-46.4%</font></font>,
<font color="#ff0000">-46.4%</font>,
<font size="2">3,737</font>,
<font size="2"><font color="#ff0000">-461</font></font>,
<font color="#ff0000">-461</font>,
<font size="2">,825</font>,
<font size="2">6,542,980</font>,
<font size="2">4</font>]
我要抓取的站点是 http://www.boxofficemojo.com/yearly/chart/?yr=2015&p=.htm。 该站点有一个电影列表,对于每部电影,我想在 table 中获取以下信息,不包括日期。
我遇到了麻烦,因为文本没有链接或任何 class 标签。我已经尝试使用多种方法,但其中 none 有效。
这是我目前使用的一种方法,只是为了获取每部电影的排名。 我希望输出只是一个由每部电影的排名组成的列表列表,然后是另一个包含每部电影列表、周末总收入等的列表。
listOfRanks = [[1, 1, 1,], [1, 2, 3], [3, 5,1]], etc.
listOfWeekendGross = [[208,806,270,106588440,54200000], [111111111, 222222222, 333333333]]
def getRank(item_url):
href = item_url[:37]+"page=weekend&" + item_url[37:]
response = requests.get(href)
soup = BeautifulSoup(response.content, "lxml") # or BeautifulSoup(response.content, "html5lib")
rank = soup.select('tbody > tr > td > center > table > tbody > tr > td > font')
print rank
这是我调用此函数的地方 -
def spider(max_pages):
url = 'http://www.boxofficemojo.com/yearly/chart/?page=' + str(max_pages) + '&view=releasedate&view2=domestic&yr=2015&p=.htm'
source_code = requests.get(url)
plain_text = source_code.text
soup = BeautifulSoup(plain_text)
for link in soup.select('td > b > font > a[href^=/movies/?]'):
href = 'http://www.boxofficemojo.com' + link.get('href')
getRank(href)
问题是 getRank(href) 方法没有正确地将排名添加到列表中。我认为问题在于这条线 -
rank = soup.select('tbody > tr > td > center > table > tbody > tr > td > font')
这可能不是获取此文本的正确方法。
我怎样才能从该站点获得所有排名、周末总收入等?
++++++++++++++++++++++++++++++++++
是的,问题出在您使用的选择器上。你看,该网站中的标记 非常糟糕 。 table 编码不正确,它们实际上缺少 tbody
标签,但是 Google Chrome 还是添加了它们,这就是为什么您会在 Web 开发人员工具中看到它们.
但是,正如我所说,它们不在实际的 HTML 代码中,因此如果您在你的选择器。看起来 table 有 class chart-wide
,因此您可以使用以下目标行:
rows = soup.select('.chart-wide tr')
之后,您可以迭代那些 rows
,跳过第一个(因为那是 header)并解析其他的和它们各自的单元格。
像这样:
def getRank(item_url):
href = item_url[:37]+"page=weekend&" + item_url[37:]
response = requests.get(href)
print response.status_code, "for", href
soup = BeautifulSoup(response.content) # or BeautifulSoup(response.content, "html5lib")
rows = soup.select('.chart-wide tr')
header_skipped = False
for row in rows:
if not header_skipped:
header_skipped = True
continue
headers = "Date Rank WeekendGross Change Theaters Change/Avg GrossToDate Week".split()
for header, child in zip(headers, row.children):
print header, ":", child.text
貌似这张图table是动态生成的,使用Phantomjs,一切正常
from selenium import webdriver
from bs4 import BeautifulSoup
driver = webdriver.PhantomJS()
driver.get('http://www.boxofficemojo.com/movies/?page=weekend&id=jurassicpark4.htm')
soup = BeautifulSoup(driver.page_source)
soup.select('table.chart-wide tbody tr td font')
出[1]
[<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=date&order=DESC&p=.htm"><b>Date<br>(click to view chart)</br></b></a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=rank&order=ASC&p=.htm">Rank</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=wkndgross&order=DESC&p=.htm">Weekend<br>Gross</br></a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=perchange&order=DESC&p=.htm">%<br>Change</br></a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=theaters&order=DESC&p=.htm">Theaters</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=theaterchange&order=ASC&p=.htm">Change</a> / </font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=avg&order=DESC&p=.htm">Avg.</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=todategross&order=DESC&p=.htm">Gross-to-Date</a></font>,
<font size="2"><a href="/movies/?page=weekend&id=jurassicpark4.htm&sort=weeknum&order=ASC&p=.htm">Week<br>#</br></a></font>,
<font size="2"><a href="/weekend/chart/?yr=2015&wknd=24&p=.htm"><b>Jun 12–14</b></a></font>,
<font size="2">1</font>,
<font size="2">8,806,270</font>,
<font size="2">-</font>,
<font size="2">4,274</font>,
.
.
.
<font size="2">0,373,420</font>,
<font size="2">3</font>,
<font size="2"><a href="/weekend/chart/?yr=2015&wknd=27&p=.htm"><b>Jul 3–5</b></a></font>,
<font size="2">2</font>,
<font size="2">,242,025</font>,
<font size="2"><font color="#ff0000">-46.4%</font></font>,
<font color="#ff0000">-46.4%</font>,
<font size="2">3,737</font>,
<font size="2"><font color="#ff0000">-461</font></font>,
<font color="#ff0000">-461</font>,
<font size="2">,825</font>,
<font size="2">6,542,980</font>,
<font size="2">4</font>]