با پایتون محتوای یه تعداد خیلی زیادی فایل رو عوض کنین...
سلام
امروز درگیر یه تسک باحال بودم :)
باید یه چیزی حدود ۱۰۰-۱۵۰ تا فایل HTML رو دونه دونه بررسی میکردم، و صفحاتی که داخلشون تگ a با اتربیوت href به یه سایت واقعی وجود داشت رو حذف میکردم و با `#` جایگزین میکردم.
چند بار رگولار اکسپرشن ها رو تست کردم و جواب نداد داستانش! مدام به ارور میخوردم و دقیق نبود سیستمش. مجبور شدم یدی کار کنم. بعد از حدود ۱ ساعت یه فکر خوب به ذهنم رسید و عملیاتیش کردم.
اول از همه، باید beautifulsoup رو نصب کنم. به هر دلیل روی انوایرمنت عمومی سیستمعامل نصب میکنم.
یه فایل `converter.py` درست میکنم، و کد پایین رو توش مینویسم:
import os
from bs4 import BeautifulSoup
files_list = list()
غیر از beautifulsoup برای دور دور کردن توی فایلها و پوشه ها، به ماژول os هم نیاز دارم.
مسئله این هستش که فایلهای HTML ام، به صورت صدها فایل `index.html` هر کدوم توی یه پوشه مربوط به خودش با اسم گذاری درست هستن.
یه ابجکت لیست خالی هم میسازم که اسمفایلهایی که پیدا میکنم رو بذارم داخلش.
for root, dir, files in os.walk("132/"):
for _ in files:
if _.endswith(".html"):
file_name = os.path.join(root, _)
files_list.append(file_name)
این کد خیلی ساده و سر راسته. دارم میگردم توی فایلها و پوشههای موجود توی پوشه `132/` و بررسی میکنم که اگر اخر اسمشون `.html`دارن، پت کامل بهشون ایجاد و داخل لیست اسمفایلها اضافه بشه. تا اینجا کار بخصوصی صورت نگرفته.
اصل کار و ایدهام از اینجا شروع میشه
for _ in files_list:
with open(_, "r") as tmp_file:
html = tmp_file.read()
soup = BeautifulSoup(html.decode("utf-8"), "html.parser")
روی اسامی فایلهایی که توی لیست گذاشته بودم لوپ میزنم و دونه دونه اونها رو باز میکنم. هر فایل باز شده داخل متغییر `html` میذارمش و بعد اون رو تبدیل به ابجکت کلاس `BeautifulSoup` میکنم.
این وسط یه نکته مهم وجود داره و اون این هستش که چون توی فایلهام متن فارسی دارم و چون دارم با پایتون واقعی (پایتون۲) کار میکنم، مجبورم کل متنها رو دیکد کنم تا به ارور یا مشکل نخورم در طول کار کردن با دیتام.
for link in soup.find_all("a"):
try:
href = link['href']
except:
pass
if href.startswith("http"):
link['href'] = "#"
هر فایل که باز شده بود و تبدیل به ابجکت قابل پارس توسط بیوتیفلسوپ شده رو میام روی کل تگ های a اش لوپ میزنم. من کل انکور تگها رو دارم، ولی همشون رو نمیخوام. کل انکور تگ رو هم لازم ندارم! فقط بخش `href` رو میخوام. بنابراین این مقدار رو داخل یه متغییر به اسم `href` میریزم. در ادامه، با یه شرط بررسی میکنم که اگر متغییرم دیتای داخلش با `http` شروع میشه (لینکهای به بیرون توی فایلهای من یا `http` هستن یا `https` و غیر از این دو پروتکل لینک دیگهای ندارم پس امن هستش کارم)، کل دیتا رو بریزم دور و مقدار `#` بهش بدم.
نکتهای که وجود داره این هستش که کلی انکور تگ ناقص(`href` نداشته باشه) ممکنه پیدا بشه توی این همه فایل. این فرانت دولوپرها همیشه از این کارها میکنن! منم میام کل کدم رو توی یه ترایکچ خالی میذارم و بنابراین، اگر لینکی خواست ارور بده که `href` ندارم، من نادیدهاش میگیرم. البته این مدل اکسپشنهندلینگ حل مشکل نیست! و توی پروداکشن نباید بیاد. مثلا چون دارم با احتمالا یه ابجکت از نوع `dict` کار میکنم، اکسپشنهایی که `KeyError` رو ریز کردن رو دراپ کنم و بقیه رو واقعا هندل کنم! :) ولی خوب...
try:
with open(_, "w") as tmp_file:
tmp_file.write(soup.encode("utf-8"))
except Exception as e:
print str(e)
pass
فایل رو باز میکنم دوباره، دیتا رو توش میخوام بنویسم. دیتا رو دیکد کرده بودم، بنابراین باید انکد کنمش دوباره تا مشکلی پیش نیاد. یه هندلینگ اکسپشن همینجوری هم اینجا میذاریم، ولی چون اینجا مهمه که چی میشه و چی نمیشه، یه پرینت هم میذارم که اگر به ارور خوردم، بتونم برم و دستی کار رو درستش کنم.
چند جای کد از متغییر `_` استفاده کردم که اگر نمیدونید چی هست، باید بگم که کاربردش این هستش که وقتی اسمی به ذهنتون نمیرسه برای یه وریبل یا نمیخواید باهاش کار بکنید و فقط باید باشه، از این استفاده میکنین.
- يكشنبه, ۲ دی ۱۳۹۷، ۰۲:۳۹ ب.ظ