Scrapy - 格式化内容和HTML属性

0 投票
2 回答
652 浏览
提问于 2025-04-18 12:35

我正在用Scrapy抓取一个网站的数据,准备导入,但在处理内部链接的格式时遇到了一些麻烦。

看看下面这个HTML结构:

<div class="PageContent">
    <a href="files/documents/path1.pdf">Click me</a>
    <a href="files/documents/path2.pdf">Click me</a>
    <a href="files/documents/path3.pdf">Click me</a>
</div>

这是我使用的XPath:

item["page_content"] = response.xpath("//div[@class='PageContent']".encode("ascii","ignore"))[0].extract().replace('\r','')

这个方法效果不错。我还检查了响应中是否有文件,并且也下载了它们。我对FilesPipeline进行了定制,让它保留相对路径和文件名,而不是把它们变成一个GUID。

pdf_urls = nodes.xpath(u'//a[@href[contains(., ".pdf")]]/@href'.encode("utf-8")).extract()  

这个部分也运行得很好。

我需要做的是修改item["page_content"],在HREF属性的前面加上一个字符串,如果文件扩展名是.PDF的话。我尝试过这个(还有各种不同的版本):

for attr in response.xpath(u'//a[@href[contains(., ".pdf")]]/@href'):
    attr[href] = "/new/dir/in/front" + attr

但都没有成功。而且,即使我成功修改了这些数据,怎么才能让items["page_content"]不变成一个包含这些新属性的列表呢?我想要的结果是:

items["page_content"] =     <div class="PageContent">
                                <a href="/new/dir/in/front/files/documents/path1.pdf">Click me</a>
                                <a href="/new/dir/in/front/files/documents/path2.pdf">Click me</a>
                                <a href="/new/dir/in/front/files/documents/path3.pdf">Click me</a>
                            </div>

提前谢谢你!

2 个回答

0

你有没有试过手动生成 items["page_content"] 呢?可以试试像这样:

items['page_content'] = []
for attr in response.xpath(u'//a[@href[contains(., ".pdf")]]/@href'):
    items['page_content'].append("/new/dir/in/front" + attr)
1

我试了很久这个问题,最后决定用一个XML/HTML解析器来整理我的数据。这样做简单多了,速度也快,而且控制得更好。把这个答案发出来,希望能帮助到遇到类似问题的人。

这里有一段代码:

from lxml import html as HTML
from lxml import etree as ET

...

doc_pattern = ('//a[@href['
           ' contains(., ".pdf") or' 
           ' contains(., ".dot") or'
           ' contains(., ".rtf") or' 
           ' contains(., ".doc") or'
           ' contains(., ".xls") or' 
           ' contains(., ".docx") or'
           ' contains(., ".xlsx")'
           ']]')

def parse_page_html(pattern, 
                    response=response, 
                    HTML=HTML, 
                    ET=ET
                    ):

            parser  = ET.HTMLParser(remove_comments=True, remove_blank_text=True)
            content = response.xpath(pattern)[0].extract()
            content = content.encode("ascii","ignore")
            content = content.replace('\r','').replace('\n','').replace('\t','')
            body    = HTML.fromstring(content, parser=parser)

            for links in body.xpath(doc_pattern):
                links.attrib['href'] = remove_absolute_url( links.attrib['href'] )

...
content = ET.tostring(body)
return content

我之前从来没有做过这样的事情(而且只用Python学了大约3个小时),但是lxml让我在不到45分钟内就上手了。我最后重写了很多代码来利用这个工具,结果非常棒。

撰写回答