Пример #1
0
    def parseContactsTable(self, table):
        def convertDaysCountKV(texts):
            result = []
            for text in texts:
                # 5月1日など月が記載されている箇所があるため、月以前を削除する
                if re.search(r'月', text) is not None:
                    _, text = re.split(r'月', text)
                # 誤字で日が件と表示されている箇所があるため、日と件の両方で分割
                key, count, *_ = re.split(r'日|件', text)
                result.append({'day': int(key), 'count': int(count)})
            return result

        items = table.findAll('tr')[1:]
        res_dict = []
        for item in items:
            # span
            # td属性からテキストを取得
            span, sum_number_tmp, individuals_tmp = list(
                map(self.get_text_rm_p_tag, item.findAll('td')))
            individuals = list(individuals_tmp.split('、'))

            # spanからreturnするdictonaryのlistを取得する
            target_list = TimeUtil().get_dt_dict_from_text(span)

            # 日ごとの件数をkvで取得
            days_count_dict = convertDaysCountKV(individuals)

            for day_count in days_count_dict:

                target_list = list(map(lambda x: {
                                   '日付': x['日付'], '小計': day_count['count'] if x['day'] == day_count['day'] else x['小計'], 'day': x['day']}, target_list))

            res_dict.extend(target_list)
        # 一次変数の'day'を消して返却
        return list(map(lambda x: {'日付': x['日付'], '小計': x['小計']}, res_dict))
Пример #2
0
    def create_new_patient_dict(self, patient_soup, scr):

        # 対象の階層のデータだけ抽出する
        data = scr.find_h4(patient_soup)
        patients = []
        patient = {}
        patient["No"] = StringUtil.exclude_info_number(data.text)
        # 県外事例は除外
        inside_checker = StringUtil()
        for index, sibling in enumerate(data.next_siblings):
            # if index % 2 != 0:  # 改行コードはスキップする
            if hasattr(sibling, "text"):
                target = sibling.text
            else:
                target = sibling
            # h4属性の場合、新たなpatient dictを作成する
            if sibling.name == 'h4':
                # 患者情報でない余計な情報の場合、dictへの格納を行わない
                if len(patient.keys()) > 1 and inside_checker.exclude_outside(patient["No"]):

                    patient["退院"] = None

                    if patient["発生判明日"] is not None:
                        patient["発生判明日"] = TimeUtil().convert_wareki_to_ad(
                            patient["発生判明日"])
                    patients.append(self.sort_patients_dict(patient))
                patient = {}
                patient["No"] = StringUtil.exclude_info_number(target)
                continue

            # 年代|性別|発生判明日|居住地の情報をセットする
            flg, key, value = StringUtil.set_key_value(target)
            if flg and key not in patient:
                patient[key] = value

            # h2タグが表示された時点で別と患者情報の表示は終了する
            if sibling.name == 'h2':
                patient["退院"] = None
                if patient["発生判明日"] is not None:
                    patient["発生判明日"] = TimeUtil().convert_wareki_to_ad(
                        patient["発生判明日"])
                patients.append(self.sort_patients_dict(patient))
                break
        print(patients)
        self.patient_list = list(filter(lambda x: re.search(
            r'\d', x['No']) is not None, patients))
Пример #3
0
    def create_patients_summary_dict(self, patient_list):
        # patients_summaryの作成
        patients_summary = TimeUtil().create_dt_dict(datetime.datetime.now())
        # patient_listから"発生判明日"のみのリストを作成
        patients_summary_tmp = list(map(lambda x: x["発生判明日"], patient_list))

        for k, g in groupby(patients_summary_tmp):
            patients_summary = list(map(lambda x: {"日付": x["日付"], "小計": len(
                list(g)) if x['日付'] == k else x['小計']}, patients_summary))

        # 小計が0とならない最新の日付までのリストにする
        patients_summary = sorted(patients_summary, key=lambda x: x['日付'])
        patients_summary = JsonChecker.exclude_zero_max_date(patients_summary)
        self.patients_summary_data['data'] = patients_summary
Пример #4
0
def getPatientDict(index_html, scr, update_datetime):
    # 発生状況等の取得
    url = scr.getTargetUrl(index_html, 'info_coronavirus_prevention.html')
    soup = scr.getContent(url)
    # テーブル情報を取得する
    try:
        dataset = scr.parseSingleTable(soup)
    except ValueError as e:
        raise e
    # pdf格納folderの作成
    path_op = PathOperator()
    path_op.create_path('pdf')

    # 県外事例は除外
    inside_checker = StringUtil()
    patient_data_tmp = []
    patients_summary_tmp = []
    for data in dataset:
        if inside_checker.exclude_outside(data[0]):

            # 格納先のファイル名を作成
            file_name = path_op.set_downlaod_file_name(
                'pdf', path_op.get_file_name(data[3]))
            scr.downloadPdf(data[3], file_name)
            output_file = os.path.splitext(os.path.basename(file_name))[0]
            output_path = os.path.join('./text', output_file + '.txt')
            is_duplicated, number_char = StringUtil().is_duplicate_data(
                data[0])

            # 重複している場合
            if is_duplicated:
                for n in number_char:
                    # print('No:{} リリース日:{} 判明日:{} Link:{}'.format(n, data[1].strip(), data[2].strip(), output_path))
                    patient_data_tmp.append({
                        "No": n,
                        "リリース日": data[1].strip(),
                        "link": output_path
                    })
                    patients_summary_tmp.append(data[2].strip())

            # 単一の場合
            else:
                # print('No:{} リリース日:{} 判明日:{} Link:{}'.format(number_char, data[1].strip(), data[2].strip(), output_path))
                patient_data_tmp.append({
                    "No": number_char,
                    "リリース日": data[1].strip(),
                    "link": output_path
                })
                patients_summary_tmp.append(data[2].strip())

    # convertの実行
    path_op.create_path('text')
    convert_txt = PdfParser()
    convert_txt.executeConvert()

    # テキストからjsonの作成
    parser = TextParser()
    patient_list = []

    # patientの作成
    for tmp in patient_data_tmp:
        result = parser.text2dict(tmp['No'], tmp['link'])
        result.update(tmp)
        result.update({'退院': None})
        del result['link']
        patient_list.append(result)
    patients = {}
    patients['__comments'] = "陽性患者の属性"
    patients['date'] = update_datetime
    # Noに数字が入らない場合の処理(例:"再陽性")
    nan_patient_list = list(
        filter(lambda x: re.search(r'\d', x['No']) is None, patient_list))
    number_patient_list = list(
        filter(lambda x: re.search(r'\d', x['No']) is not None, patient_list))
    insert_patient_list = sorted(
        number_patient_list,
        key=lambda x: int(re.sub(r'県|内|例|目', '', x['No'])))
    insert_patient_list.extend(nan_patient_list)
    patients['data'] = insert_patient_list
    # patients_summaryの作成
    patients_summary_data = {}
    patients_summary_data['__comments'] = "陽性患者数"
    patients_summary_data['date'] = update_datetime
    patients_summary = TimeUtil().create_dt_dict(datetime.datetime.now())
    for k, g in groupby(patients_summary_tmp):
        patients_summary = list(
            map(
                lambda x: {
                    "日付": x["日付"],
                    "小計": len(list(g)) if x['日付'] == k else x['小計']
                }, patients_summary))

    # 小計が0とならない最新の日付までのリストにする
    patients_summary = sorted(patients_summary, key=lambda x: x['日付'])
    jc = JsonChecker()
    patients_summary = jc.exclude_zero_max_date(patients_summary)
    patients_summary_data['data'] = patients_summary

    return patients, patients_summary_data
def tmu_object():
    tmu = TimeUtil()
    yield tmu
 def __init__(self, base):
     self.base = base
     self.time_util = TimeUtil()
class Scraper:
    def __init__(self, base):
        self.base = base
        self.time_util = TimeUtil()

    def getTargetUrl(self, base_url: str, target_url: str):
        r = requests.get(self.base + base_url)
        r.encoding = r.apparent_encoding
        soup = BeautifulSoup(r.text, 'html.parser')
        elems = soup.find(href=re.compile(target_url))
        return elems.get('href')

    def getContent(self, url: str):
        r = requests.get(self.base + url)
        r.encoding = r.apparent_encoding
        return BeautifulSoup(r.text, 'html.parser')

    def downloadPdf(self, pdf_url: str, path_name: str) -> None:
        r = requests.get(self.base + pdf_url, stream=True)
        with open(path_name, 'wb') as fd:
            for chunk in r.iter_content(chunk_size=2000):
                fd.write(chunk)

    def parseSingleTable(self, soup_data):
        table = soup_data.findAll('table')[0]
        numbers = table.findAll("th")[1:]
        rows = table.findAll("tr")[1:]
        dataset = []
        for number, row in zip(numbers, rows):
            day_proved, tmp = row.findAll("td")
            # dayにpタグが付いているパターンがある
            correct_date = tmp.findAll('a')[-1]
            day_release = correct_date.getText()
            try:
                ad_day_release = self.time_util.convert_wareki_to_ad(
                    day_release.strip())
                ad_day_proved = self.time_util.convert_wareki_to_ad(
                    day_proved.text.strip())
            except ValueError as e:
                raise e

            link = correct_date.get('href')

            dataset.append(
                [number.find('p').text, ad_day_release, ad_day_proved, link])
        return dataset

    def findAllTable(self, soup_data):
        return soup_data.findAll('table')

    def find_p_and_h4(self, soup_data):
        return soup_data.findAll(['p', 'h4'])

    def find_h4(self, soup_data):
        return soup_data.find('h4')

    def get_text_rm_p_tag(self, soup):
        if len(soup.findAll('p')) != 0:
            return soup.findAll('p')[0].text.strip()
        else:
            return soup.text.strip()

    def parseContactsTable(self, table):
        def convertDaysCountKV(texts):
            result = []
            for text in texts:
                # 5月1日など月が記載されている箇所があるため、月以前を削除する
                if re.search(r'月', text) is not None:
                    _, text = re.split(r'月', text)
                # 誤字で日が件と表示されている箇所があるため、日と件の両方で分割
                key, count, *_ = re.split(r'日|件', text)
                result.append({'day': int(key), 'count': int(count)})
            return result

        items = table.findAll('tr')[1:]
        res_dict = []
        for item in items:
            # span
            # td属性からテキストを取得
            span, sum_number_tmp, individuals_tmp = list(
                map(self.get_text_rm_p_tag, item.findAll('td')))
            individuals = list(individuals_tmp.split('、'))

            # spanからreturnするdictonaryのlistを取得する
            target_list = TimeUtil().get_dt_dict_from_text(span)

            # 日ごとの件数をkvで取得
            days_count_dict = convertDaysCountKV(individuals)

            for day_count in days_count_dict:

                target_list = list(
                    map(
                        lambda x: {
                            '日付':
                            x['日付'],
                            '小計':
                            day_count['count']
                            if x['day'] == day_count['day'] else x['小計'],
                            'day':
                            x['day']
                        }, target_list))

            res_dict.extend(target_list)
        # 一次変数の'day'を消して返却
        return list(map(lambda x: {'日付': x['日付'], '小計': x['小計']}, res_dict))