我正在使用scrapy刮掉这个页面:
https://en.wikipedia.org/wiki/List_of_shopping_malls_in_the_United_States
链接位于:
data = response.xpath('//*[@id="mw-content-text"]/ul[9]/li').extract()
数据是:
[<Selector xpath='//*/li' data=u'<li><a href="/wiki/Ala_Moana_Center" tit'>,
<Selector xpath='//*/li' data=u'<li><a href="/wiki/Kahala_Mall" title="K'>,
<Selector xpath='//*/li' data=u'<li><a href="/wiki/Pearlridge" title="Pe'>,
<Selector xpath='//*/li' data=u'<li><a href="/wiki/Prince_Kuhio_Plaza" t'>,
<Selector xpath='//*/li' data=u'<li><a href="/wiki/Victoria_Ward_Centers'>]
我需要的链接是:
https://en.wikipedia.org + href
例如:
'https://en.wikipedia.org'+'/ wiki / Ala_Moana_Center'
这样做我正在使用正则表达式
link = 'https://en.wikipedia.org' + re.findall('href="([^"]+)',str(data[0]))[0]
name = re.findall('href="([^"]+)',str(data[0]))[0].replace('/wiki/','').replace('_',' ')
问题在于,通过这种方法,我必须创建一个循环来获取链接,有一种方法可以直接从scrapy或至少以更有效的方式创建这些链接吗?
答案 0 :(得分:2)
Nono,不需要正则表达式,将XPath直接指向href
属性:
data = response.xpath('//*[@id="mw-content-text"]/ul[9]/li/a/@href').extract()
然后,使用urlparse.urljoin()
构建绝对网址,使用response.url
作为基础:
from urlparse import urljoin
base_url = response.url
data = [urljoin(base_url, link)
for link in response.xpath('//*[@id="mw-content-text"]/ul[9]/li/a/@href').extract()]
作为旁注,我并不特别喜欢XPath表达式中的ul[9]
部分 - 一般来说,使用索引并不可靠并且很容易破坏 - 并且您无法阅读和理解表达式。看起来,您正在寻找夏威夷购物中心。根据前面的Hawaii
标签找到链接:
//a[. = "Hawaii"]/following::ul/li/a/@href
使用这个表达式很容易看出你实际找到了什么。
以下是按州分组链接的方法,例如Shell:
$ scrapy shell https://en.wikipedia.org/wiki/List_of_shopping_malls_in_the_United_States
>>> from urlparse import urljoin
>>> from pprint import pprint
>>>
>>> base_url = response.url
>>>
>>> data = {}
>>> for state in response.xpath("//h3[span[@class='mw-headline']]"):
... state_name = state.xpath(".//a[@title]/text()").extract_first()
... links = [urljoin(base_url, link) for link in state.xpath('./following-sibling::*[1]//li/a/@href').extract()]
... data[state_name] = links
>>>
>>> pprint(data)