[英]Is it possible to find the nodes with same dom structure
我從Scrapy的許多網站中抓取了很多html(內容相似),而dom的結構卻不同。
例如,其中一個站點使用以下結構:
<div class="post">
<section class='content'>
Content1
</section>
<section class="panel">
</section>
</div>
<div class="post">
<section class='content'>
Conent2
</section>
<section class="panel">
</section>
</div>
我想提取數據Content
和Content2
。
雖然另一個站點可能使用這樣的結構:
<article class="entry">
<section class='title'>
Content3
</section>
</article>
<article class="entry">
<section class='title'>
Conent4
</section>
</article>
我想提取數據Content3
和Content4
。
最簡單的解決方案是為所有站點一一標記所需的數據xpath。 那將是一件乏味的工作。
所以我想知道結構是否可以自動提取。 實際上,我只需要位於重復的根節點(在上面的示例中為div.post
和article.entry
),就可以使用某些特定規則提取數據。
這可能嗎?
順便說一句,我不確定這種算法的名稱,所以這篇文章的標簽可能是錯誤的,如果是真的,可以隨意修改。
您必須至少知道一些常見的模式才能制定確定性的提取規則。 以下解決方案非常原始,絕非最佳選擇,但它可能會幫助您:
# -*- coding: utf-8 -*-
import re
import bs4
from bs4 import element
import scrapy
class ExampleSpider(scrapy.Spider):
name = "example"
start_urls = ['http://quotes.toscrape.com/']
def parse(self, response):
min_occurs = 5
max_occurs = 1000
min_depth = 7
max_depth = 7
pattern = re.compile('^/html/body/.*/(span|div)$')
extract_content = lambda e: e.css('::text').extract_first()
#extract_content = lambda e: ' '.join(e.css('*::text').extract())
doc = bs4.BeautifulSoup(response.body, 'html.parser')
paths = {}
self._walk(doc, '', paths)
paths = self._filter(paths, pattern, min_depth, max_depth,
min_occurs, max_occurs)
for path in paths.keys():
for e in response.xpath(path):
yield {'content': extract_content(e)}
def _walk(self, doc, parent, paths):
for tag in doc.children:
if isinstance(tag, element.Tag):
path = parent + '/' + tag.name
paths[path] = paths.get(path, 0) + 1
self._walk(tag, path, paths)
def _filter(self, paths, pattern, min_depth, max_depth, min_occurs, max_occurs):
return dict((path, count) for path, count in paths.items()
if pattern.match(path) and
min_depth <= path.count('/') <= max_depth and
min_occurs <= count <= max_occurs)
它是這樣的:
為了構建路徑字典,我只是使用BeautifulSoup
文檔,並計算每個元素路徑的出現次數。 以后可以在過濾任務中使用它,以僅保留最多重復的路徑。
接下來,我根據一些基本規則過濾出路徑。 為了保留路徑,它必須:
min_occurs
,最多max_occurs
倍。 min_depth
,最大為max_depth
。 pattern
。 可以以類似方式添加其他規則。
最后一部分遍歷過濾后留下的路徑,並使用一些使用extract_content
定義的通用邏輯從元素中提取內容。
如果您的網頁非常簡單,並且可以推斷出此類規則,則可能會起作用。 否則,您將不得不考慮某種我認為是機器學習的任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.