CoolFace
Modelpublic

acl-crown-analysis/acl-crown-analysis-code

sourceHugging Facemitupdated 9mo agoView on Hugging Face
0likes
fetch_from_Ss.py258 linesDownload Raw Back to root
1import os
2import csv
3import yaml
4import time
5import requests
6import concurrent.futures
7from pathlib import Path
8
9API_KEY = "YOUR_API_KEY_HERE"
10
11BASE_DIR = Path(__file__).resolve().parent.parent
12DATA_DIR = BASE_DIR / "data"
13DATA_FALSE_DIR = BASE_DIR / "data-false"
14CONFIG_FILE = BASE_DIR / "config" / "venues_top.yaml"
15
16HEADERS = {"x-api-key": API_KEY}
17
18def request_with_retry(url, params=None, max_retries=5):
19    for i in range(max_retries):
20        try:
21            response = requests.get(url, params=params, headers=HEADERS, timeout=15)
22            if response.status_code == 200:
23                return response
24            elif response.status_code == 429:
25                wait_time = 5 * (i + 1)
26                print(f"Rate limit exceeded (429). Waiting {wait_time}s... (Attempt {i+1}/{max_retries})")
27                time.sleep(wait_time)
28                continue
29            elif 500 <= response.status_code < 600:
30                print(f"Server error ({response.status_code}). Retrying... (Attempt {i+1}/{max_retries})")
31                time.sleep(2)
32                continue
33            else:
34                return response
35        except requests.exceptions.RequestException as e:
36            print(f"Network error: {e}. Retrying... (Attempt {i+1}/{max_retries})")
37            time.sleep(2)
38            
39    print(f"Failed to fetch {url} after {max_retries} attempts.")
40    return None
41
42def load_config():
43    if not CONFIG_FILE.exists():
44        print(f"Config file not found: {CONFIG_FILE}")
45        return set(), set()
46
47    with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
48        config = yaml.safe_load(f)
49    
50    top_confs = set(conf.lower() for conf in config.get('top_conferences', []))
51    top_journals = set(jour.lower() for jour in config.get('top_journals', []))
52    
53    return top_confs, top_journals
54
55def search_paper(title):
56    url = "https://api.semanticscholar.org/graph/v1/paper/search"
57    params = {
58        "query": title,
59        "limit": 1,
60        "fields": "paperId,title,year"
61    }
62    
63    response = request_with_retry(url, params)
64    
65    if response and response.status_code == 200:
66        data = response.json()
67        if data.get('data'):
68            return data['data'][0]
69    elif response:
70        print(f"Error searching paper: {response.status_code} - {response.text}")
71        
72    return None
73
74def get_citations(paper_id):
75    citations = []
76    offset = 0
77    limit = 1000
78    total = 0
79    
80    detail_url = f"https://api.semanticscholar.org/graph/v1/paper/{paper_id}"
81    r = request_with_retry(detail_url, params={"fields": "citationCount"})
82    
83    if r and r.status_code == 200:
84        total = r.json().get('citationCount', 0)
85    else:
86        return [], 0
87
88    if total == 0:
89        return [], 0
90
91    print(f"Fetching {total} citations for paper {paper_id}...")
92    
93    while True:
94        url = f"https://api.semanticscholar.org/graph/v1/paper/{paper_id}/citations"
95        params = {
96            "fields": "year,venue",
97            "offset": offset,
98            "limit": limit
99        }
100        
101        response = request_with_retry(url, params)
102        
103        if response and response.status_code == 200:
104            data = response.json()
105            batch = data.get('data', [])
106            if not batch:
107                break
108            
109            citations.extend(batch)
110            offset += len(batch)
111            
112            if offset >= total or len(batch) < limit:
113                break
114            
115            time.sleep(1.0)
116        else:
117            print(f"Error fetching citations page.")
118            break
119            
120    return citations, total
121
122def is_top_venue(venue_name, top_list):
123    if not venue_name:
124        return False
125    v = venue_name.lower()
126    for top in top_list:
127        if top in v:
128            return True
129    return False
130
131def process_single_row(row, top_confs, top_journals):
132    title = row.get('title')
133    if not title:
134        return None, None
135
136    paper_info = search_paper(title)
137    
138    if paper_info:
139        paper_id = paper_info['paperId']
140        row['paperId'] = paper_id
141        
142        citations, count = get_citations(paper_id)
143        row['citationCount'] = count
144        
145        top_conf_count = 0
146        top_journal_count = 0
147        year_counts = {y: 0 for y in range(2014, 2025)}
148        
149        for cit in citations:
150            citing_paper = cit.get('citingPaper', {})
151            if not citing_paper:
152                continue
153                
154            year = citing_paper.get('year')
155            if year and 2014 <= year <= 2024:
156                year_counts[year] += 1
157            
158            venue = citing_paper.get('venue')
159            if is_top_venue(venue, top_confs):
160                top_conf_count += 1
161            elif is_top_venue(venue, top_journals):
162                top_journal_count += 1
163        
164        row['top_conf_citations'] = top_conf_count
165        row['top_journal_citations'] = top_journal_count
166        for year in range(2014, 2025):
167            row[f'citations_{year}'] = year_counts[year]
168        
169        return row, True
170    else:
171        return row, False
172
173def process_files():
174    top_confs, top_journals = load_config()
175    
176    if not DATA_DIR.exists():
177        print(f"Data directory not found: {DATA_DIR}")
178        return
179
180    files = [f for f in os.listdir(DATA_DIR) if f.endswith('.csv')]
181    
182    for filename in files:
183        file_path = DATA_DIR / filename
184        false_file_path = DATA_FALSE_DIR / filename.replace('.csv', '.txt')
185        
186        DATA_FALSE_DIR.mkdir(parents=True, exist_ok=True)
187        
188        print(f"\nProcessing file: {filename}")
189        
190        not_found_papers = []
191        fieldnames = []
192        
193        with open(file_path, 'r', encoding='utf-8') as f:
194            reader = csv.DictReader(f)
195            fieldnames = reader.fieldnames
196            rows = list(reader)
197        
198        if false_file_path.exists():
199            with open(false_file_path, 'r', encoding='utf-8') as f:
200                not_found_papers = [line.strip() for line in f.readlines()]
201
202        total_rows = len(rows)
203        batch_size = 10
204        max_workers = 3
205        
206        indices_to_process = []
207        for i, row in enumerate(rows):
208            if row.get('title') and not (row.get('paperId') and row.get('citationCount')):
209                indices_to_process.append(i)
210        
211        print(f"Total rows: {total_rows}, Rows to process: {len(indices_to_process)}")
212
213        for i in range(0, len(indices_to_process), batch_size):
214            batch_indices = indices_to_process[i:i + batch_size]
215            
216            print(f"Processing batch {i//batch_size + 1}/{(len(indices_to_process) + batch_size - 1)//batch_size} (Rows {batch_indices[0]+1}-{batch_indices[-1]+1})...")
217
218            with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
219                future_to_index = {
220                    executor.submit(process_single_row, rows[idx], top_confs, top_journals): idx 
221                    for idx in batch_indices
222                }
223                
224                for future in concurrent.futures.as_completed(future_to_index):
225                    idx = future_to_index[future]
226                    try:
227                        updated_row, found = future.result()
228                        if updated_row:
229                            rows[idx] = updated_row
230                            title = updated_row.get('title')
231                            
232                            if found:
233                                print(f"  [✓] Found: {title[:40]}...")
234                                if title in not_found_papers:
235                                    not_found_papers.remove(title)
236                            else:
237                                print(f"  [x] Not Found: {title[:40]}...")
238                                if title not in not_found_papers:
239                                    not_found_papers.append(title)
240                    except Exception as exc:
241                        print(f"Row {idx} generated an exception: {exc}")
242
243            print(f"Saving progress after batch...")
244            with open(file_path, 'w', encoding='utf-8', newline='') as f:
245                writer = csv.DictWriter(f, fieldnames=fieldnames)
246                writer.writeheader()
247                writer.writerows(rows)
248            
249            if not_found_papers:
250                with open(false_file_path, 'w', encoding='utf-8') as f:
251                    for t in not_found_papers:
252                        f.write(f"{t}\n")
253            
254            time.sleep(1)
255
256if __name__ == "__main__":
257    process_files()
258