刚学爬虫,也没看具体的文档,所以遇到这个问题多试了几次,记录下。
爬取豆瓣电影Top250,用Xpath很方便直观,在选取节点中,电影的名称节点有相同的两个属性:
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飞(港) / 刺激1995(台)</span>
比如上面的前两个,class="title",但是我只想要第一个电影名称。
我先这么做:
url = 'https://movie.douban.com/top250'
html = etree.HTML(get_one_page(url)) 注:get_one_page(url)是单独编写的爬取网页获得html文档的函数
results = html.xpath('//ol//div/div[@class="info"]//a/span[@class="title"]/text()')
for result in results:
print(result)
得到的结果是:
肖申克的救赎
/ The Shawshank Redemption
霸王别姬
这个杀手不太冷
/ Léon
阿甘正传
/ Forrest Gump
...
后来想到美丽汤会只会选择第一个匹配的节点:
url = 'https://movie.douban.com/top250'
html = etree.HTML(get_one_page(url))
results = html.xpath('//ol//div/div[@class="info"]//a/span[@class="title"]')
for result in results:
name = BeautifulSoup(etree.tostring(result), 'lxml')
print(name.span.string)
初次这么写,得到的结果还是跟上面一样,Xpath选择中不能到span节点,改一下,只选到a节点:
url = 'https://movie.douban.com/top250'
html = etree.HTML(get_one_page(url))
results = html.xpath('//ol//div/div[@class="info"]//a')
for result in results:
name = BeautifulSoup(etree.tostring(result), 'lxml')
print(name.span.string)
这么着就得到了纯中文的电影名称:
肖申克的救赎
霸王别姬
这个杀手不太冷
阿甘正传
美丽人生
泰坦尼克号
千与千寻
这时突然觉得Xpath选择中肯定有一个简单的方法可以选择某一个节点,而且就是下标,果不其然。
url = 'https://movie.douban.com/top250'
html = etree.HTML(get_one_page(url))
results = html.xpath('//ol//div/div[@class="info"]//a/span[@class="title"][1]/text()')
for result in results:
print(result)
下标从1开始,改为2得到:
/ The Shawshank Redemption
/ Léon
/ Forrest Gump
/ La vita è bella
/ Titanic
...
在此过程中还遇到一个问题,之前得到电影名称用有非中文的名称,装进了一个表,
name = ['肖申克的救赎', '\xa0/\xa0The Shawshank Redemption', '霸王别姬', '这个杀手不太冷', '\xa0/\xa0Léon', '阿甘正传', '\xa0/\xa0Forrest Gump', '美丽人生', '\xa0/\xa0La vita è bella']
这里面有'\xa0'的字符,查看网上的说法是:该字符是不间断空格符。我们通常所用的空格是 \x20 ,是在标准ASCII可见字符 0x20~0x7e 范围内。而 \xa0 属于 latin1 (ISO/IEC_8859-1)中的扩展字符集字符,代表空白符nbsp(non-breaking space)(如开头HTML文本中第三行的显示)。 latin1 字符集向下兼容 ASCII ( 0x20~0x7e )。
当时没有解决爬取的时候筛选的问题,想着直接在这个列表了去掉,弄了个正则表达式。
pattern = re.compile(r'^\xa0/\xa0.*?')
for i in name:
if re.match(pattern, i):
name.remove(i)
continue
print(name)
name = ['肖申克的救赎', '霸王别姬', '这个杀手不太冷', '阿甘正传', '美丽人生']