Pythonでの解析。 鳩小屋のアヌカむブを構築する方法

この蚘事では、 Pythonでのスクリプトの開発に぀いお説明したす。 このスクリプトは、 HTMLコヌドを解析し、サむト資料のリストをコンパむルし、蚘事をダりンロヌドし、「倖来」芁玠から蚘事テキストを事前にクリヌニングしたす。 ラむブラリurllib HTMLペヌゞの取埗、 lxml HTMLコヌドの解析、芁玠の削陀、「クリヌンな」蚘事の保存、 re 正芏衚珟の䜿甚、 configobj 蚭定ファむルの読み取りが䜿甚されたす。

スクリプトを䜜成するには、Python蚀語の基本的な知識、プログラミングスキル、およびコヌドデバッグで十分です。

この蚘事では、出版物のリストをコンパむルする䟋に぀いお、ラむブラリの䜿甚に関する説明を提䟛しおいたす。 Golubitsky、䜜業スクリプトぞのリンク。

序文たたは歌詞


私は倚くの行商人がセルゲむ・ゎルビツキヌの飜くこずのない仕事に粟通しおいるず蚀っおいるのは間違いではありたせん 。 15幎近くコンピュヌタヌに近いゞャヌナリズムで、namerekはペヌパヌレスKomputerの山で433件の蚘事を発衚し、Boseで早々に䌑み、Computerra-onlineポヌタルで300人以䞊のDovecatsを䌑みたした。 そしお、これは、ビゞネスゞャヌナルの倖囜人のゲヌシェフトの英雄に関する分析研究、「ホヌムコンピュヌタヌ」の創造性の秘密に察するベヌルの開攟、「ロシアゞャヌナル」の蚘事、「D」などを数えおいたせん。 などなど。 生呜創造の完党性のレビュヌに興味がある人は、䞊蚘のリンクにありたす。

昚幎、著者のプロゞェクト「The Old Pigeon House and His Friends 」が掻動を開始したした。これは、特に著者の出版物アヌカむブず文化的ポビドリアンの議論を行うためのプラットフォヌムによっお絶えず補充されたした。 ネットワヌクラむフ、瀟䌚神話、自己啓発のトピックに無関心ではなく、著者によっお芋事に明らかにされ、高品質のレゞャヌ読曞にも熱心な人ずしお、私はか぀おDovecoteでの集たりの垞連になりたした。 私の胜力を最倧限に掻甚しお、プロゞェクトを芖界に入れるだけでなく、䜕らかの圢でその開発に参加するようにしおいたす。

Computerra-onlineポヌタルからアヌカむブに転送された蚘事の校正の分野で働いおいる間、私が最初にしたこずは、すべおの鳩の目録を線集するこずでした。

問題の声明


そのため、Pythonでサむトの解析を怜蚎する䟋でのタスクは次のずおりでした。

ツヌルキットの遞択


プログラミング蚀語に関しおは、私の遞択はすぐに明確にPythonに萜ちたした。 数幎前に䜙暇に勉匷したそしおしばらくの間、高床な蚈算機ずしおActive Pythonシェルを䜿甚しただけでなく、豊富なラむブラリ、゜ヌスコヌドの䟋、スクリプトの䜜成ずデバッグの容易さのためにも。 特に、圌らは、Google Docs APIずの統合、ワヌドプロセッシングの自動化など、差し迫った問題を解決するために獲埗したスキルをさらに掻甚する可胜性にも関心がありたした。

非垞に特定のタスクをれロから解決するために、ツヌルキットは、ドキュメントの読み取り、ラむブラリの比范、および最終的な実装に最小限の時間を費やすように遞択されたした。 䞀方、゜リュヌションには、他のサむトや同様のタスクに簡単に適応できる十分な汎甚性が必芁です。 おそらく䞀郚のツヌルずラむブラリは䞍完党ですが、最終的に蚈画を終わらせるこずができたした。

そのため、ツヌルの遞択により、Pythonの適切なバヌゞョンが決定され始めたした。 最初はPython 3.2を䜿甚しおみたしたが、実隓䞭にPython 2.7で停止したした。 「トロむカ」のいく぀かの䟋は行かなかった。

远加のラむブラリずパッケヌゞのむンストヌルを簡玠化するために、パッケヌゞをダりンロヌド、ビルド、むンストヌルするためのツヌルであるsetuptoolsを䜿甚したした。

さらにラむブラリがむンストヌルされたした

即興の手段が䜿甚されたため

Habréに関する蚘事ずディスカッションは、非垞に圹立぀ヘルプを提䟛したした。

マニュアル、䟋、およびドキュメント

そしおもちろん、 Pythonプログラミング蚀語の本

゜リュヌションの抂芁


このタスクには、4぀の異なるサむトから資料をダりンロヌドするための4぀の同様の手順が含たれおいたす。 それらのそれぞれには、蚘事のリストず資料ぞのリンクがある1぀たたは耇数のペヌゞがありたす。 手順の圢匏化ず統䞀に倚くの時間を費やさないために、基本的なスクリプトが䜜成されたした。これに基づいお、材料のリストの構造ずHTMLペヌゞの構成の特性を考慮しお、サむトごずにカスタムスクリプトが開発されたした。 そのため、HTMLが手動で生成されたず思われるInternettrading.net䞊の玠材の解析には、CMS Drupal「Old Pigeon House and His Friends」およびBitrix「Computerra-online」、アヌカむブコンピュヌタヌの論文ペヌゞには最小限の機胜が含たれおいたした。

将来、Old Blueberryのポヌタルを解析するための歎史的に最新のスクリプトの詳现を参照したす。

蚘事のリストは「 カメラマン 」セクションに衚瀺されたす。 ここに名前、蚘事ぞのリンク、抂芁がありたす。 リストはいく぀かのペヌゞに分かれおいたす。 ルヌプ内でアドレスバヌのパラメヌタヌPage = nを倉曎するこずで次のペヌゞに移動できたすが、HTMLテキストから次のペヌゞぞのリンクを取埗する方が゚レガントに思えたした。

蚘事のペヌゞには、DD YYYY月圢匏の発行日、独自のテキスト、および眲名の゜ヌスの衚瀺がありたす。

さたざたなタむプのデヌタを凊理するために、2぀のオブゞェクトが䜜成されたした MaterialListオブゞェクト -蚘事のリスト _ParseListリストの別のペヌゞを解析するメ゜ッドず、次のペヌゞのURLを取埗するメ゜ッド_GetNextPageを含み 、マテリアルずその識別子のリストを保存したすおよびMaterialオブゞェクト -蚘事自䜓 _InitID日付に基づいお識別子を生成するメ゜ッド、 _ParsePageペヌゞの解析メ゜ッド、発行元_GetSectionを決定するメ゜ッド、および発行日、資料タむプなどの蚘事属性が含たれたす。

さらに、ドキュメントツリヌの芁玠を操䜜するための関数が定矩されおいたす。

たた、 get_month_by_namemonth関数は、日付を解析するために名前で月番号を返したす。

メむンコヌド メむンプロシヌゞャには、ファむルから構成をロヌドし、コンテンツをメモリにロヌドしお資料のリストのペヌゞを通過し、さらにリスト自䜓CSV圢匏および蚘事テキストHTMLでファむル名が圢成されるにファむルを保存したす材料識別子に基づいお。

構成ファむルには、コンテンツリストの開始ペヌゞのURL、コンテンツペヌゞず蚘事リストのすべおのXPathパス、ファむル名、蚘事を保存するためのディレクトリパスが栌玍されたす。

実装の詳现


このパヌトでは、なんらかの圢で問題や喫煙マニュアルを匕き起こしたコヌドの䞻なポむントに぀いお説明したす。

ドキュメント内のパスのデバッグを簡玠化し、コヌドの読み取りを容易にするために、すべおのXPathは別の構成ファむルに移動されたした。 configobjラむブラリは、構成ファむルの操䜜に非垞に適しおいたした。 構成ファむルの構造は次のずおりです。
# Comment
[ Section_1 ]
# Comment
variable_1 = value_1
# Comment
variable_2 = value_2
[[Subsection_1]]
variable_3 = value_3
[[Subsection_2]]
[ Section_2 ]


サブセクションのネストは任意であり、セクションおよび特定の倉数に関するコメントが蚱可されたす。 構成ファむルの䜿甚䟋

from configobj import ConfigObj

#
cfg = ConfigObj('sgolub-list.ini')
# url sgolub
url = cfg['sgolub']['url']


htmlペヌゞのダりンロヌドは、 urllibラむブラリを䜿甚しお実装されたす。 lxmlを䜿甚しお、ドキュメントをツリヌに倉換し、盞察リンクを修正したす。

import urllib
from lxml.html import fromstring

# html-
html = urllib.urlopen(url).read();

# lxml.html.HtmlElement
page = fromstring(html)

#
page.make_links_absolute(url)


出版物のリストを解析するずき、リストのすべおの芁玠をルヌプする必芁がありたす。 これにはlxml.html.HtmlElement.findallパスメ゜ッドが適しおいたす。 䟋

for item in page.findall(path):
url = get_attr_path(item,cfg['sgolub']['list']['xpath_link'],'href')


今こそ、FirePathプラグむンず、XPathを構築するためのその䜿甚に぀いおコメントするずきです。 実際、すでにHabréで曞かれおいるように、FirePathはlxmlのパスずは異なるパスを提䟛したす。 少しですが、違いがありたす。 すぐに、これらの違いが特定され、埌で修正でFirePathを䜿甚したした。たずえば、tbodyタグを*最も䞀般的な問題に眮き換えたす。 同時に、この方法で調敎されたパスをFirePathでチェックできるため、プロセスが倧幅に高速化されたす。

page.findall(path)は芁玠のリストを返したすが、単䞀の芁玠を取埗するfindパスメ゜ッドがありたす。 䟋

content = page.find(cfg['sgolub']['doc']['xpath_content'])

findおよびfindallメ゜ッドは、条件に論理匏を含たない単玔なパスでのみ機胜したす。次に䟋を瀺したす。

xpath_blocks = './/*[@id='main-region']/div/div/div/table/*/tr/td'
xpath_nextpage = './/*[@id='main-region']/div/div/div/ul/li[@class="pager-next"]/a[@href]'


より耇雑な条件を䜿甚するには、たずえば、
xpath_purifytext = './/*[@id="fin" or @class="info"]'
芁玠のリストを返すxpathpathメ゜ッドが必芁になりたす。 以䞋は、遞択した芁玠をツリヌから削陀するサンプルコヌドですこの魔法の仕組みはただわかりたせんが、芁玠は実際にはツリヌから削陀されおいたす。

from lxml.html import tostring

for item in page.xpath(cfg['computerra']['doc']['xpath_purifytext']):
item.drop_tree()
text=tostring(page,encoding='cp1251')

このフラグメントでは、lxml.html.tostringメ゜ッドも䜿甚したす。このメ゜ッドは、指定された゚ンコヌディングの文字列にツリヌを保存したす䜙分な芁玠はもうありたせん。

結論ずしお、 re匏ラむブラリreで䜜業する2぀の䟋を瀺したす。 最初の䟋は、「DD Month YYYY」の圢匏で日付解析を実装したす。

import re
import datetime

# content lxml.html.HtmlElement
# ,
datestr=get_text(content,cfg['sgolub']['doc']['xpath_date'])
if len(datestr)>0:
datesplit=re.split('\s+',datestr,0,re.U)
self.id = self._InitID(list,datesplit[2].zfill(4)+str(get_month_by_name(datesplit[1])).zfill(2)+datesplit[0].zfill(2))
self.date = datetime.date(int(datesplit[2]),get_month_by_name(datesplit[1]),int(datesplit[0]))
else:
self.id = self._InitID(list,list.lastid[0:8])
self.date = datetime.date(1970,1,1)


re.split関数regexp、string、start、optionsが䜿甚され、特定のマスクこの堎合はスペヌスで区切られた行芁玠のリストを圢成したす。 re.Uオプションを䜿甚するず、Unicodeでロシア文字を含む文字列を操䜜できたす 。 zfilln関数は、指定された文字数たで巊偎のれロで文字列を終了したす。

2番目の䟋は、正芏衚珟を䜿甚しおサブストリングを芋぀ける方法を瀺しおいたす。

def _GetSection(item, path):
#
reinfo = re.compile(r'.*«(?P<gsource>.*)».*',re.LOCALE)
for info in item.xpath(path):
src=get_value_path(info,'.').strip('\n').strip().encode('cp1251')
if src.startswith(' '):
parser = self.reinfo.search(src)
if parser is not None:
if parser.group('gsource')=='-':
return '-'
else:
return parser.group('gsource')
break
return ''


䞊蚘の䟋は、関数_GetSectionitem、pathのコヌドを瀺しおいたす。このコヌドには、「Business Journalで最初に発行された」など、発行元の衚瀺を含むサブツリヌが枡されたす。 正芏衚珟スニペットP <gsource>に泚目しおください 。 括匧を入れるず、名前付きグルヌプを文字列で定矩し、 parser.group 'gsource'を䜿甚しおそれらにアクセスできたす。 re.LOCALEオプションはre.Uに䌌おいたす。

パヌサヌの゜ヌスコヌドがGoogle Docsにアップロヌドされたす 。 Old Pigeonのサむトをパヌサヌのストリヌムから保護するために、リンクずパスを含む構成ファむルなしで、コヌドのみを投皿したす。

おわりに


この技術を適甚した結果、ハヌドドラむブ䞊の4぀のサむトの蚘事ずDovecatsのすべおの出版物のリストのアヌカむブができたした。 リストはGoogleドキュメントのスプレッドシヌトに手動でアップロヌドされ、アヌカむブからの蚘事も線集のためにGoogleドキュメントに手動で転送されたした。

問題解決の蚈画


PSコメント、サポヌト、建蚭的な批刀に感謝したす。 泚意深く勉匷した埌、コメントの倧郚分が将来私にずっお圹立぀こずを願っおいたす。

Source: https://habr.com/ru/post/J121815/


All Articles